【NOIP2014模拟】木马

题目

【NOIP2014模拟】木马_第1张图片
Input

第一行包括两个整数n,type,其中type=0或1。
接下来n行两个整数Up[i]与A[i],代表基站i直传基站以及上传速率。

接下来给出一个整数Q。
接下来Q组询问,每组有若干行。
第一行两个整数x,p,代表上传的基站x和发生变动的数目。
接下来p行两个整数Cx,Cy,代表发生变动节点的编号和权值。
若type=1,(Cy xor (abs(lastans) and 16383))为真正的Cy,lastans为上一次询问的波动值,(i=1时,lastans=0)。
每两组询问中有一行空行。

Output
输出共Q行,每行一个整数C为第i次询问时系统的波动值。

【NOIP2014模拟】木马_第2张图片

分析

首先,这题强制在线,其次这题求的背景是一棵树上的一条链上排过序的数列的特殊的和,我们可以发现对于一种数值,并且它在这条链上出现了x次,若x&1==0那么它对答案贡献为0,若x&1==1那么它对答案贡献值为它本身。
而我们发现这种数值最大也就只有16383个。而且我们可以基于离线的思想,先处理出本身的答案,然后再根据它给出的条件来更改。还有我们做到一个点,那么它儿子的答案可以从它本身传递得来。
所以我们对于题目所要求的答案所用的数据结构也就出来了——主席树。
我们在原本的主席树上再多维护一个c[i]表示第i棵主席树上的答案,那么c[i]=c[left[i]]+或-c[right[i]],是加是减,我们只用判断一下左边的节点数量即可。
到此便可以很好的解决这个问题了。
而插入和删除操作其实差不多的,一个加一一个减一
其他的照样维护就可以了。

var
    n,tpe,lastans,i,j,m,tot,num,w,k,bz:longint;
    sum,left,right,root,c:array[0..3200000] of longint;
    b,next,last,cx,cy,a:array[0..1000000] of longint;
procedure make(var x:longint;y,l,r,e,o:longint);
var mid:longint;
begin
    if (o=0)or(x=0) then begin
       inc(tot);x:=tot;
    end else x:=y;
    left[x]:=left[y];
    right[x]:=right[y];
    sum[x]:=sum[y]+1;
    if l=r then begin
       if sum[x] mod 2<>0 then c[x]:=e else c[x]:=0;
       exit;
    end;
    mid:=(l+r)shr 1;
    if mid>=e then make(left[x],left[y],l,mid,e,o) else make(right[x],right[y],mid+1,r,e,o);
    sum[x]:=sum[left[x]]+sum[right[x]];
    if sum[left[x]] mod 2=0 then c[x]:=c[left[x]]+c[right[x]] else c[x]:=c[left[x]]-c[right[x]];
end;
procedure delt(var x:longint;y,l,r,e:longint);
var mid:longint;
begin
    if x=0 then begin
       inc(tot);x:=tot;
    end else x:=y;
    left[x]:=left[y];
    right[x]:=right[y];
    sum[x]:=sum[y]-1;
    if l=r then begin
       if sum[x] mod 2<>0 then c[x]:=e else c[x]:=0;
       exit;
    end;
    mid:=(l+r)shr 1;
    if mid>=e then delt(left[x],left[y],l,mid,e) else delt(right[x],right[y],mid+1,r,e);
    sum[x]:=sum[left[x]]+sum[right[x]];
    if sum[left[x]] mod 2=0 then c[x]:=c[left[x]]+c[right[x]] else c[x]:=c[left[x]]-c[right[x]];
end;
procedure dfs(x,y:longint);
var p:longint;
begin
    make(root[x],root[y],0,16383,a[x],0);
    p:=last[x];
    while p<>0 do begin
        dfs(b[p],x);
        p:=next[p];
    end;
end;
procedure insert(x,y:longint);
begin
    inc(num);
    b[num]:=y;
    next[num]:=last[x];
    last[x]:=num;
end;
begin
    readln(n,tpe);
    readln(i,a[1]);
    for i:=2 to n do begin
        readln(j,a[i]);
        insert(j,i);
    end;
    dfs(1,0);
    readln(m);
    for i:=1 to m do begin
        readln(j,w);
        for k:=1 to w do begin
            readln(cx[k],cy[k]);
            if tpe=1 then cy[k]:=(cy[k] xor(abs(lastans)and 16383));
        end;
        for k:=1 to w do begin
            make(root[j],root[j],0,16383,cy[k],1);
            delt(root[j],root[j],0,16383,a[cx[k]]);
        end;
        lastans:=c[root[j]];
        writeln(lastans);
        for k:=1 to w do begin
            delt(root[j],root[j],0,16383,cy[k]);
            make(root[j],root[j],0,16383,a[cx[k]],1);
        end;
    end;
close(input);close(output);
end.

你可能感兴趣的:(可持久化线段树,主席树)