9
18
2013
0

【BZOJ2819】Nim【树状数组+LCA+DFS序+手工栈+博弈论】

首先我不得不吐槽一下BZOJ,出这么一道pascal无解的题目有什么意思呢?我就算优化到极限pascal还是TLE,而C++一个复杂度比我没有花之前的程序居然11S就A了,C++秀优越也用不着这样啊。

先搞个DFS序,这样的话就可以用树状数组来维护了。最终的答案就是add_up(s[k1]) xor add_up(s[k2]) xor w[closefather(k1,k2)],s是dfs序中最先出现的位置,w是权值。最近公共祖先就用LCA搞掉。就如题目所说,这道题目要用手工栈,不然会在爆栈OJ爆栈。接下来是我无比惨烈的解题截图。(不要怪我没节操的贴了代码)

 


program p2819;
    type   
        bian=record
            next,point:longint;
        end;
    var
        y:array[1..500000,1..4] of longint;
        x:array[1..1000010] of longint;
        d,w,p,s,e:array[1..500010] of longint;
        f:array[1..500010,0..20] of longint;
        b:array[1..1000010] of bian;
        q,len,i,j,n,k1,k2:longint;
        ch:char;
        bo:boolean;
    function getchar:char;
        var
            ch:char;
        begin
            read(ch);
            while (ch<>'Q') and (ch<>'C') do
                read(ch);
            exit(ch);
        end;
    procedure ade(k1,k2:longint);
        begin
            inc(len);
            b[len].point:=k2;
            b[len].next:=p[k1];
            p[k1]:=len;
        end;
    procedure add(k1,k2:longint);
        begin
            ade(k1,k2);
            ade(k2,k1);
        end;
    procedure bfs;
        var
            i,j,head,now:longint;
        begin
            head:=1; now:=1; y[1,1]:=1; y[1,2]:=p[1]; y[1,3]:=0; y[1,4]:=1;
            d[1]:=1; f[1,0]:=0; s[1]:=1;
            while now>0 do begin
                i:=y[now,2];
                if (i<>0) and (b[i].point=y[now,3]) then i:=b[i].next;
                if (i=0) then begin
                    inc(head); e[y[now,1]]:=head;
                    dec(now);
                    continue;
                end;
                inc(now); y[now,1]:=b[i].point; y[now,2]:=p[y[now,1]]; y[now,3]:=y[now-1,1]; y[now,4]:=y[now-1,4]+1;
                inc(head); f[y[now,1],0]:=y[now,3]; s[y[now,1]]:=head; d[y[now,1]]:=y[now,4];
                y[now-1,2]:=b[i].next;
            end;
        end;
    function lowbit(k:longint):longint;
        begin
            exit(k and (-k));
        end;
    procedure add_in(k1,k2:longint);
        var
            i,j:longint;
        begin
            i:=k1;
            while i<=1000010 do begin
                x[i]:=x[i] xor k2;
                i:=i+lowbit(i);
            end;
        end;
    function add_up(k:longint):longint;
        var
            i,num:longint;
        begin
            i:=k; num:=0;
            while i>0 do begin
                num:=num xor x[i];
                i:=i-lowbit(i);
            end;
            exit(num);
        end;
    function go_up(k1,k2:longint):longint;
        var
            i,j,k:longint;
        begin
            for k:=0 to 20 do
                if 1 shl k>k2 then break;
            dec(k); if k<0 then exit(k1);
            j:=k1;
            for i:=0 to k do
                if k2 and (1 shl i)>0 then
                    j:=f[j,i];
            exit(j);
        end;
    function find(k1,k2:longint):longint;
        var
            i,j,k:longint;
        begin
            if d[k1]>d[k2] then begin
                i:=k1; k1:=k2; k2:=i;
            end;
            k2:=go_up(k2,d[k2]-d[k1]);
            if k1=k2 then exit(k1);
            for k:=1 to 20 do
                if 1 shl k>=d[k1] then break;
            dec(k);
            for i:=k downto 0 do
                if f[k1,i]<>f[k2,i] then begin
                    k1:=f[k1,i]; k2:=f[k2,i];
                end;
            exit(f[k1,0]);
        end;
    begin
        readln(n);
        for i:=1 to n do
            read(w[i]);
        len:=0;
        fillchar(p,sizeof(p),0);
        fillchar(b,sizeof(b),0);
        for i:=1 to n-1 do begin
            readln(k1,k2);
            add(k1,k2);
        end;
        fillchar(d,sizeof(d),0);
        len:=0;
        bfs;
        fillchar(x,sizeof(x),0);
        for i:=1 to n do begin
            add_in(s[i],w[i]);
            add_in(e[i],w[i]);
        end;
        for i:=1 to 20 do begin
            bo:=false;
            for j:=1 to n do
                if (1 shl i)<d[j] then begin
                    bo:=true; 
                    f[j,i]:=f[f[j,i-1],i-1];
                end;
            if bo=false then break;
        end;
        readln(q);
        for i:=1 to q do begin
            ch:=getchar;
            if ch='Q' then begin
                readln(k1,k2);
                j:=add_up(s[k1]) xor add_up(s[k2]) xor w[find(k1,k2)];
                if j=0 then writeln('No') else writeln('Yes');
            end else begin
                readln(k1,k2);
                add_in(s[k1],w[k1]); add_in(e[k1],w[k1]);
                add_in(s[k1],k2); add_in(e[k1],k2);
                w[k1]:=k2;
            end;
        end;
    end.
Category: 数据结构 | Tags: | Read Count: 1814

登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter

Host by is-Programmer.com | Power by Chito 1.3.3 beta | Theme: Aeros 2.0 by TheBuckmaker.com