首页 > 代码库 > Codeforces Round #260 (Div. 2)

Codeforces Round #260 (Div. 2)

A. Laptops

题意:给两个数列,问是否存在i,j,是的a[i]<a[j] 而 b[i]>b[j]

题解:先把一维排序,就是问是否存在逆序对。我写了个树状数组。。。貌似从a小到大扫一遍保存遇到的b的最大值即可

代码:

 1 var s,a,b,c:array[0..150000] of longint; 2     i,n,m,tot:longint; 3 procedure sort(l,r:longint); 4  var i,j,x,y:longint; 5  begin 6  i:=l;j:=r;x:=a[(i+j)>>1]; 7  repeat 8   while a[i]<x do inc(i); 9   while a[j]>x do dec(j);10   if i<=j then11    begin12    y:=a[i];a[i]:=a[j];a[j]:=y;13    y:=b[i];b[i]:=b[j];b[j]:=y;14    inc(i);dec(j);15    end;16  until i>j;17  if i<r then sort(i,r);18  if j>l then sort(l,j);19  end;20 procedure init;21  begin22  readln(n);23  for i:=1 to n do readln(a[i],b[i]);24  sort(1,n);25  tot:=0;26  i:=0;tot:=0;27  for i:=1 to n do28   begin29   if (i=1) or (a[i]<>a[i-1]) then30    begin31    inc(tot);c[tot]:=b[i];32    end;33   if b[i]>c[tot] then c[tot]:=b[i];34   end;35  end;36 procedure add(x:longint);37  begin38  while x<=n do39   begin40   inc(s[x]);41   inc(x,x and (-x));42   end;43  end;44 function sum(x:longint):longint;45  var t:longint;46  begin47  t:=0;48  while x>0 do49   begin50   inc(t,s[x]);51   dec(x,x and (-x));52   end;53  exit(t);54  end;55 56 function check:boolean;57  begin58  fillchar(s,sizeof(s),0);59  for i:=tot downto 1 do60    begin61    if sum(c[i]-1)>0 then exit(true);62    add(c[i]);63    end;64  exit(false);65  end;66 begin67   init;68   if check then writeln(Happy Alex) else writeln(Poor Alex);69 end.
View Code

B. Fedya and Maths

题意:求 (1^n+2^n+3^n+4^n) mod 5

题解:不难看出,4 mod 5=-1  3 mod 5=-2

      i) 当n为奇数时  有  (1^n+2^n+3^n+4^n) mod 5=(1^n+(-1)^n+2^n+(-2)^n) mod 5=0 正好抵消

      ii)当n为偶数时,(1^n+2^n+3^n+4^n) mod 5=(1+1+2^n+2^n) mod 5 =(2+2*(-1)^n/2) 所以又要分情况

           ① n/2为奇数时, 原式=2-2=0

           ② n/2为偶数时,原式=2+2=4

     所以总结起来就是如果能被4整除,=4 else =0

代码:

1 var z:longint;s:ansistring;2 begin3   readln(s);4   if length(s)>=2 then val(copy(s,length(s)-1,2),z)5   else val(s,z);6   if  z mod 4=0 then writeln(4)7   else writeln(0);8 end.     
View Code

C. Boredom

题意:给一个数列,你如果选了a[k],那么a[k]+1与a[k]-1都不能选了,选a[k]获得的收益为a[k]*a[k]出现的次数,求最大收益

题解:显然不能只选奇数或只选偶数 如 1 1 1 1 2 3 4 当然应该选1 和 4

所以我们应该DP,令f[i]表示选i 可以获得的最大收益,g[i]表示不选i 获得的最大收益,则:

f[i]=g[i-1]+w[i] g[i]=max(g[i-1],f[i-1])

代码:

 1 var f,g,v,a:array[-1..150000] of int64; 2     i,n,x:longint; 3     function max(x,y:int64):int64; 4      begin 5        if x>y then exit(x) else exit(y); 6      end; 7  8 procedure init; 9  begin10    readln(n);11    for i:=1 to n do read(a[i]);12    for i:=1 to n do inc(v[a[i]]);13  end;14 procedure main;15  begin16    fillchar(f,sizeof(f),0);17    fillchar(g,sizeof(g),0);18    for i:=1 to 100000 do19     if v[i]=0 then begin f[i]:=f[i-1];g[i]:=g[i-1];end20     else21      begin22        f[i]:=max(f[i-2],g[i-1])+i*v[i];23        g[i]:=max(g[i-1],f[i-1]);24      end;25    writeln(max(f[100000],g[100000]));26  end;27 28 begin29   init;30   if n=1 then writeln(a[1]) else main;31 end.                      
View Code

D. A Lot of Games
题意:给你一些串,两个人轮流在一个字符串后面添加字母(初始为空),每个时刻都必须使当前的字符串为所有给定的字符串中的某个或多个的前缀。

无法填字母者输。游戏一共进行K次,每次的loser将下一次first,请问先手必胜还是后手必胜?

题解:我的想法是这样的

先把所有的字符串建成一棵trie树,使用布尔变量来表示每个节点是必胜状态还是必败状态,可以通过一次dfs求出

定义0节点为初始节点,它的后继有 ab。。z然后分情况讨论:

i)如果0的后继中只有必败状态,那么first将一直输到第k轮

ii)如果0的后继中只有必胜状态,那么赢家依次是 first,second,first,second。。。最后赢家由k的就来决定

iii)如果0的后继中既有必胜状态又有必胜状态,那么first可以选择一直输到第k-1轮,然后赢掉第k场比赛

代码:

 1 const maxn=50000+100; 2 var s:ansistring; 3     f:array[0..maxn,0..30] of longint; 4     sg,flag:array[0..30*maxn] of boolean; 5     i,n,tot,k:longint; 6     can1,can2:boolean; 7 procedure insert; 8  var x,y,i:longint; 9  begin10    readln(s);x:=0;11    for i:=1 to length(s) do12     begin13      y:=ord(s[i])-ord(a)+1;14      if f[x,y]=0 then15       begin16         inc(tot);17         f[x,y]:=tot;18       end;19      x:=f[x,y];20     end;21    flag[x]:=true;22  end;23 procedure init;24  begin25    readln(n,k);tot:=0;26    for i:=1 to n do insert;27  end;28 procedure dfs(x:longint);29  var can:boolean;i:longint;30  begin31    if flag[x] then begin sg[x]:=true;exit;end;32    can:=false;33    for i:=1 to 26 do34     if f[x,i]<>0 then35      begin36        dfs(f[x,i]);37        if not(sg[f[x,i]]) then can:=true;38      end;39    sg[x]:=can;40  end;41 function check:string;42  begin43    dfs(0);44    can1:=false;can2:=false;45    for i:=1 to 26 do46     if f[0,i]<>0 then47      if sg[f[0,i]] then can1:=true else can2:=true;48    if can1 and can2 then exit(First);49    if can1 and not(can2) then50      begin51        if  odd(k) then exit(First) else exit(Second);52      end;53    if can2 and not(can1) then exit(Second);54  end;55 begin56  init;57  writeln(check);58 end.                       
View Code

E题是神题,看起来就不可做。。。