bzoj 2120 线段树套平衡树
先吐下槽,改了快一个小时,最后发现是SBT的delete写错了,顿时就有想死的心。。。。。
首先对于这道题,我们应该先做一下他的小问题,bzoj1878,虽然和这道题几乎一点关系没有,
但是能给我们一个思路的启发
我们先考虑没有修改,只有区间询问
内个我下面的糖果是画笔的意思。。。我也不知道咋着题就读错了。。。。
那么对于一个糖果i,假设他的颜色是col,那么我们找到col颜色上一次出现的位置,为color[i],
那么对于一个区间L R里的color值,我们要找不同的颜色,那么假设一种颜色在L R里出现多次
那么这些糖果的color值除了最先出现的以外,剩下的color值都大于等于L,也就是我们要找在区间
L R里的color值比L小的个数就行了。我们可以用线段树套平衡树来比较容易的实现这一过程
//时间复杂度是O(nlog^2(n))的,1878做不了
树套树就相当于维护color数组用的
那么我们在修改一个位置的颜色的时候,假设把位置I的颜色改为y,原来的颜色为x
那么我们需要修改的是
i位置后面第一个颜色为X的color值改为i的color值
I位置的color值改为i前面最后一个颜色为Y的位置
I位置后面第一个颜色为Y的color值改为I
这样就行了,那么我们为了快速找到“I位置后面第一个颜色为X的糖果的位置”,需要对于每种颜色
建一颗平衡树,关键字为位置,只需要找到后继就行了
/************************************************************** Problem: 2120 User: BLADEVIL Language: Pascal Result: Accepted Time:2024 ms Memory:16280 kb ****************************************************************/ //By BLADEVIL type rec =record left, right, root :longint; end; var n, m :longint; a :array[0..10010] of longint; t :array[0..30010] of rec; c_pred, c_root :array[0..1000010] of longint; color :array[0..10010] of longint; tot :longint; b_left, b_right :array[0..500000] of longint; b_size, b_key :array[0..500000] of longint; procedure left_rotate(var t:longint); var k :longint; begin k:=b_right[t]; b_right[t]:=b_left[k]; b_left[k]:=t; b_size[k]:=b_size[t]; b_size[t]:=b_size[b_left[t]]+b_size[b_right[t]]+1; t:=k; end; procedure right_rotate(var t:longint); var k :longint; begin k:=b_left[t]; b_left[t]:=b_right[k]; b_right[k]:=t; b_size[k]:=b_size[t]; b_size[t]:=b_size[b_left[t]]+b_size[b_right[t]]+1; t:=k; end; procedure maintain(var t:longint;flag:boolean); begin if not flag then begin if b_size[b_left[b_left[t]]]>b_size[b_right[t]] then right_rotate(t) else if b_size[b_right[b_left[t]]]>b_size[b_right[t]] then begin left_rotate(b_left[t]); right_rotate(t); end else exit; end else begin if b_size[b_right[b_right[t]]]>b_size[b_left[t]] then left_rotate(t) else if b_size[b_left[b_right[t]]]>b_size[b_left[t]] then begin right_rotate(b_right[t]); left_rotate(t); end else exit; end; maintain(b_left[t],false); maintain(b_right[t],true); maintain(t,true); maintain(t,false); end; procedure insert(var t:longint;v:longint); begin if t=0 then begin inc(tot); t:=tot; b_left[t]:=0; b_right[t]:=0; b_size[t]:=1; b_key[t]:=v; end else begin inc(b_size[t]); if v<b_key[t] then insert(b_left[t],v) else insert(b_right[t],v); maintain(t,v>=b_key[t]); end; end; procedure build(x,l,r:longint); var mid :longint; i :longint; begin t[x].left:=l; t[x].right:=r; t[x].root:=0; for i:=l to r do insert(t[x].root,color[i]); if l=r then exit; with t[x] do mid:=(left+right) div 2; build(2*x,l,mid); build(2*x+1,mid+1,r); end; procedure init; var i :longint; begin read(n,m); for i:=1 to n do read(a[i]); for i:=1 to n do begin color[i]:=c_pred[a[i]]; c_pred[a[i]]:=i; end; for i:=1 to n do c_root[a[i]]:=0; for i:=1 to n do insert(c_root[a[i]],i); build(1,1,n); end; function select(t,v:longint):longint; begin if t=0 then exit(0); if b_key[t]>=v then select:=select(b_left[t],v) else select:=select(b_right[t],v)+b_size[b_left[t]]+1; end; function query(x,l,r,y:longint):longint; var mid :longint; begin if (t[x].left=l) and (t[x].right=r) then begin query:=select(t[x].root,y); exit; end; with t[x] do mid:=(left+right) div 2; if l>mid then query:=query(x*2+1,l,r,y) else if r<=mid then query:=query(x*2,l,r,y) else query:=query(x*2,l,mid,y)+query(x*2+1,mid+1,r,y); end; procedure ask(l,r:longint); begin writeln(query(1,l,r,l)); end; function delete(var t:longint;v:longint):longint; begin dec(b_size[t]); if (b_key[t]=v) or (v>b_key[t]) and (b_right[t]=0) or (v<b_key[t]) and (b_left[t]=0) then begin delete:=b_key[t]; if (b_left[t]=0) or (b_right[t]=0) then t:=b_left[t]+b_right[t] else b_key[t]:=delete(b_left[t],v+1); end else if v>b_key[t] then delete:=delete(b_right[t],v) else delete:=delete(b_left[t],v); end; procedure t_change(x,y,z,xx:longint); var mid :longint; begin delete(t[x].root,y); insert(t[x].root,z); if t[x].left=t[x].right then exit; with t[x] do mid:=(left+right) div 2; if xx>mid then t_change(2*x+1,y,z,xx) else t_change(2*x,y,z,xx); end; function pred(t,v:longint):longint; begin if t=0 then exit(0); if b_key[t]>=v then pred:=pred(b_left[t],v) else begin pred:=pred(b_right[t],v); if pred=0 then pred:=b_key[t]; end; end; function succ(t,v:longint):longint; begin if t=0 then exit(-1); if b_key[t]<=v then succ:=succ(b_right[t],v) else begin succ:=succ(b_left[t],v); if succ=-1 then succ:=b_key[t]; end; end; procedure change(x,y:longint); var w1, w2, w3 :longint; begin if a[x]=y then exit; w1:=a[x]; w2:=pred(c_root[w1],x); w3:=succ(c_root[w1],x); if w3<>-1 then t_change(1,x,w2,w3); delete(c_root[w1],x); w1:=w2; w3:=succ(c_root[y],x); w2:=pred(c_root[y],x); if w3<>-1 then t_change(1,w2,x,w3); t_change(1,w1,w2,x); a[x]:=y; insert(c_root[y],x); end; procedure main; var i :longint; ch :char; x, y :longint; begin readln; for i:=1 to m do begin read(ch); readln(x,y); if ch='Q' then ask(x,y) else change(x,y); end; end; begin init; main; end.