Description
Input
Output
Sample Input
5 and 1
3 5 2 7 1
Sample Output
1 1
2 1
5 1
1 3
Data Constraint
题解
据说这是到NOI级别的题目?
怎么数据水到可以让过掉?
虽说出题人被强烈谴责,但是我依然在比赛时利用水法水到了60分的好成绩。
烂透了。
20%
直接暴力即可。
40%
我们考虑到opt是xor操作,处理xor最大值的方式最好就是用trie这个强力的算法。
直接暴力建trie树,长度不大,也就16。
60%
此60%乃type=0的情况。
我们发现不需要考虑方案数。
继续利用trie做,离线建trie,维护每个数字最早出现时间。
如果是and操作,考虑把1子树合并到0子树上去。询问操作也是贪心。
or操作同理。
当然,我没打过。
70%~80%
在60%的基础上,考虑那个神奇的and操作。
我们发现,对于第i个数,and操作是只和a[i]中1的位置有关。
我们考虑新建一个数组表示状态为s的方案有多少种。
利用dfs直接暴力构造a[i]的情况然后拿去与f匹配即可。
100%
由于上面的情况只考虑了and,那么像上面的思路一样考虑or说不定就过了呢?
然鹅出题人丧心病狂地出了一大堆655365,怎么办?
真·100%
我们发现,由于二进制长度为16。
而这个16又很难搞什么dp之类的。
有一个套路——把它分成一半!
设DP方程表示前8位状态为i,在之前出现过的所有情况与后八位j&或|的后八位的最大值。
再记录一个来记录方案数即可。
求答案?
设i之前某个数可以分成:第i个数可以分成:
每次枚举之前的一个数的a
那么答案即为:(or是一样的)
转移?
把当前的加入答案。
我们每次枚举之前出现过的b
那么转移即为(or是一样的)
秒啊♂
注意!我们在区分and和or的时候,不要用字符串的判断,及其的慢。
标程
var
i,j,k,l,n,m,kind,x,y,tot,p,q,zd:longint;
a:array[1..100000] of longint;
tree:array[0..1000000,0..1] of longint;
bzz,gs:array[0..1000000] of longint;
f,g:array[0..256,0..256] of longint;
op:array[0..65536] of longint;
jl:array[1..16] of longint;
mi:array[0..16] of longint;
s,t:ansistring;
bz:boolean;
procedure insert(x,y:longint);
var
j,k:longint;
begin
if y>16 then
begin
inc(gs[x]);
bzz[x]:=a[i];
exit;
end;
if tree[x,jl[y]]=0 then
begin
inc(tot);
tree[x,jl[y]]:=tot;
insert(tot,y+1);
end
else
begin
insert(tree[x,jl[y]],y+1);
end;
end;
procedure dg(x,y:longint);
begin
if x>16 then
begin
inc(op[y]);
end
else
begin
if jl[x]=1 then
begin
dg(x+1,y*2+1);
dg(x+1,y*2);
end
else
begin
dg(x+1,y*2);
end;
end;
end;
procedure find(x,y:longint);
begin
if x>16 then
begin
if op[y]>0 then
begin
if kind=1 then writeln(y,' ',op[y])
else writeln(y);
bz:=true;
end;
exit;
end
else
begin
if jl[x]=1 then
begin
if not bz then
find(x+1,y*2+1);
if not bz then
find(x+1,y*2);
end
else
begin
find(x+1,y*2);
end;
end;
end;
begin
assign(input,'binary.in');reset(input);
assign(output,'binary.out');rewrite(output);
mi[0]:=1;
for i:=1 to 16 do
begin
mi[i]:=mi[i-1]*2;
end;
readln(s);
bz:=true;
t:='';
for i:=1 to length(s) do
begin
if s[i]=' 'then
begin
bz:=false;
end
else
if (s[i]>='0') and (s[i]<='9') then
begin
if bz then n:=n*10+ord(s[i])-48
else kind:=kind*10+ord(s[i])-48;
end
else
begin
t:=t+s[i];
end;
end;
for i:=1 to n do
begin
read(a[i]);
end;
if t='xor' then
begin
for i:=1 to n do
begin
j:=a[i];
for k:=16 downto 1 do
begin
jl[k]:=j mod 2;
j:=j div 2;
end;
if i>1 then
begin
x:=0;
y:=1;
while y<=16 do
begin
if tree[x,1-jl[y]]=0 then
begin
x:=tree[x,jl[y]];
inc(y);
end
else
begin
x:=tree[x,1-jl[y]];
inc(y);
end;
end;
writeln(a[i] xor bzz[x],' ',gs[x]);
end;
insert(0,1);
end;
end
else
if t='and' then
begin
for i:=1 to n do
begin
x:=a[i] div mi[8];
y:=a[i] mod mi[8];
p:=-maxlongint;q:=0;
if i>1 then
begin
for j:=0 to mi[8]-1 do
if g[j,y]>0 then
begin
k:=(x and j)*mi[8]+f[j,y];
if k>p then
begin
p:=k;
q:=g[j,y];
end
else
if k=p then inc(q,g[j,y]);
end;
if kind=1 then writeln(p,' ',q)
else writeln(p);
end;
for j:=0 to mi[8]-1 do
begin
k:=j and y;
if k>f[x,j] then
begin
f[x,j]:=k;
g[x,j]:=1;
end
else
if k=f[x,j] then inc(g[x,j]);
end;
end;
end
else
begin
for i:=1 to n do
begin
x:=a[i] div mi[8];
y:=a[i] mod mi[8];
p:=-maxlongint;q:=0;
if i>1 then
begin
for j:=0 to mi[8]-1 do
if g[j,y]>0 then
begin
k:=(x or j)*mi[8]+f[j,y];
if k>p then
begin
p:=k;
q:=g[j,y];
end
else
if k=p then inc(q,g[j,y]);
end;
if kind=1 then writeln(p,' ',q)
else writeln(p);
end;
for j:=0 to mi[8]-1 do
begin
k:=j or y;
if k>f[x,j] then
begin
f[x,j]:=k;
g[x,j]:=1;
end
else
if k=f[x,j] then inc(g[x,j]);
end;
end;
end;
end.
end.