zoukankan      html  css  js  c++  java
  • jzoj4616. 【NOI2016模拟7.12】二进制的世界

    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级别的题目?
    怎么数据水到可以让O(216n)O(2^{16}*n)过掉?
    虽说出题人被强烈谴责,但是我依然在比赛时利用水法水到了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的位置有关。
    我们考虑新建一个数组f[s]f_{[s]}表示状态为s的方案有多少种。
    利用dfs直接暴力构造a[i]的情况然后拿去与f匹配即可。
    100%
    由于上面的情况只考虑了and,那么像上面的思路一样考虑or说不定就过了呢?
    然鹅出题人丧心病狂地出了一大堆655365,怎么办?
    真·100%
    我们发现,由于二进制长度为16。
    而这个16又很难搞什么dp之类的。
    有一个套路——把它分成一半!
    设DP方程f[i,j]f_{[i,j]}表示前8位状态为i,在之前出现过的所有情况与后八位j&或|的后八位的最大值。
    再记录一个g[i,j]g_{[i,j]}来记录方案数即可。
    求答案?
    设i之前某个数可以分成:a28+ba*2^8+b第i个数可以分成:c28+dc*2^8+d
    每次枚举之前的一个数的a
    那么答案即为:(a&c)28+f[a,d](a&c)*2^8+f_{[a,d]}(or是一样的)
    转移?
    把当前的c28+dc*2^8+d加入答案。
    我们每次枚举之前出现过的b
    那么转移即为f[c,b]=max(d&b)f_{[c,b]}=max(d&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.
    
    
    
  • 相关阅读:
    SpringMVC中静态获取request对象 Spring中获取 HttpServletRequest对象【转载】
    springcloud 的loadbalancer 轮询算法切换方法 2021.4.3
    springboot项目启动增加图标
    rabbitmq 端口作用以及修改方法
    centos8 安装rabbitmq
    springcloud config client Value获取不到信息的问题的处理方法
    springcloud config配置git作为数据源然后启动报错 If you want an embedded database (H2, HSQL or Derby), please put it on the classpath.
    Sublime Text的列模式如何操作
    centos8 安装redis
    jQuery简单的Ajax调用
  • 原文地址:https://www.cnblogs.com/RainbowCrown/p/11148348.html
Copyright © 2011-2022 走看看