bzoj 2743 树状数组离线查询
我们按照询问的右端点排序,然后对于每一个位置,记录同颜色
上一个出现的位置,每次将上上位置出现的+1,上次出现的-1,然后
用树状数组维护就好了
/************************************************************** Problem: 2743 User: BLADEVIL Language: Pascal Result: Accepted Time:11072 ms Memory:70540 kb ****************************************************************/ //By BLADEVIL var n, m, t, l :longint; pre, other, num :array[0..2000005] of longint; last, ans, first, a, pred, c :array[0..2000005] of longint; procedure connect(x,y,tot:longint); begin inc(l); pre[l]:=last[x]; last[x]:=l; other[l]:=y; num[l]:=tot; end; procedure add(x,y:longint); begin while (x<=n) do begin inc(c[x],y); x:=x+(x and -x); end; end; function ask(x:longint):longint; var sum :longint; begin sum:=0; while x>0 do begin sum:=sum+c[x]; x:=x-(x and -x); end; exit(sum); end; procedure init; var i, j :longint; x, y :longint; begin readln(n,t,m); for i:=1 to n do begin read(a[i]); if first[a[i]]<>0 then pred[i]:=first[a[i]]; first[a[i]]:=i; end; for i:=1 to m do begin readln(x,y); connect(y,x,i); end; end; procedure main; var i :longint; q, p :longint; begin for i:=1 to n do begin add(pred[pred[i]]+1,1); add(pred[i]+1,-1); q:=last[i]; while q<>0 do begin p:=other[q]; ans[num[q]]:=ask(p); q:=pre[q]; end; end; for i:=1 to m do writeln(ans[i]); end; begin init; main; end.