Description
给定一个含有n个数的序列a[1],a[2],a[3]……a[n],程序必须回答这样的询问:对于给定的i,j,k,在a[i],a[i+1],a[i+2]……a[j]中第k小的数是多少(1≤k≤j-i+1),并且,你可以改变一些a[i]的值,改变后,程序还能针对改变后的a继续回答上面的问题。你需要编一个这样的程序,从输入文件中读入序列a,然后读入一系列的指令,包括询问指令和修改指令。对于每一个询问指令,你必须输出正确的回答。第一行有两个正整数n(1≤n≤10000),m(1≤m≤10000)。分别表示序列的长度和指令的个数。第二行有n个数,表示a[1],a[2]……a[n],这些数都小于10^9。接下来的m行描述每条指令,每行的格式是下面两种格式中的一种。Q
i j k 或者 C i tQ i j k (i,j,k是数字,1≤i≤j≤n, 1≤k≤j-i+1)表示询问指令,询问a[i],a[i+1]……a[j]中第k小的数。C i t (1≤i≤n,0≤t≤10^9)表示把a[i]改变成为t。
i j k 或者 C i tQ i j k (i,j,k是数字,1≤i≤j≤n, 1≤k≤j-i+1)表示询问指令,询问a[i],a[i+1]……a[j]中第k小的数。C i t (1≤i≤n,0≤t≤10^9)表示把a[i]改变成为t。
Input
对于每一次询问,你都需要输出他的答案,每一个输出占单独的一行。
Output
Sample Input
5 3
3 2 1 4 7
Q 1 4 3
C 2 6
Q 2 5 3
3 2 1 4 7
Q 1 4 3
C 2 6
Q 2 5 3
Sample Output
3
6
6
HINT
20%的数据中,m,n≤100;
40%的数据中,m,n≤1000;
100%的数据中,m,n≤10000。
无限仰慕WJMZBMR。
看了他的集训队论文给了我很大的启发。
预祝WJMZBMR大神进入国家队。
这个是支持修改的区间第k大问题。
首先想不修改的区间第k大问题,由于权值线段树可以进行四则运算,所以可以由两棵线段树相减得到一颗描述区间的线段树,然后log查询。
这个本质是前缀和。
前缀和修改为O(n),查询为O(1),修改实在是非常慢,而且对空间要求非常大,所以我们希望将修改和查询的耗时进行平衡。
说到可修改的前缀和,容易想到树状数组,所以按修改树状数组的方式修改logn棵线段树,查询的时候访问logn棵线段树在权值线段树上查询,修改时间复杂度O(log^2),所需空间复杂度O(log^2),查询与其相同。
虽然学到了新算法,但是破灭了一个梦想觉得很不高兴。
你看啊,函数式编程不就像世界线吗……我可以从一个世界线不断前行,也可以用电话微波炉回到过去进入别的世界线……但是这样无法体现世界线的收敛,也就是即使发送dmail让世界线走到分叉也能回到注定的世界线,可是树状数组解决了这个问题,但是完全不能体现啊……………………………………………………超~不~爽。
program bzoj1901; var len,all,tot,n,m,i,j,k:longint; s,root:array [0..10001] of longint; new,dl:array [0..20001] of longint; que:array [0..10001] of record t:char; i,j,k:longint; end; left,right,sum:array [0..4000001] of longint; procedure swap (var a,b:longint);inline; begin if a=b then exit; b:=a xor b; a:=a xor b; b:=a xor b; end; procedure qsort (s,e:longint); var i,j,k:longint; begin if s>=e then exit; i:=s; j:=e; k:=dl[(s+e) div 2]; while i<=j do begin while dl[i]<k do inc(i); while dl[j]>k do dec(j); if i>j then break; swap(dl[i],dl[j]); inc(i); dec(j); end; qsort(s,j); qsort(i,e); end; function convert (now:longint):longint;inline; var mid,s,e:longint; begin s:=1; e:=all; while s<>e do begin mid:=(s+e) div 2; if new[mid]<now then s:=mid+1 else e:=mid; end; exit(s); end; procedure build (s,e,now:longint); var mid:longint; begin if s=e then exit; mid:=(s+e) div 2; inc(tot); left[now]:=tot; build(s,mid,tot); inc(tot); right[now]:=tot; build(mid+1,e,tot); end; function lowbit (x:longint):longint;inline; begin exit(x xor (x and (x-1))); end; procedure insert (p,w,x:longint);inline; var l,r,last,now,mid:longint; begin while x<=n do begin l:=1; r:=all; last:=root[x]; inc(tot); root[x]:=tot; now:=tot; repeat sum[now]:=sum[last]+p; if l=r then break; mid:=(l+r) div 2; inc(tot); if w<=mid then begin left[now]:=tot; right[now]:=right[last]; now:=tot; last:=left[last]; r:=mid; end else begin left[now]:=left[last]; right[now]:=tot; now:=tot; last:=right[last]; l:=mid+1; end; until false; x:=x+lowbit(x); end; end; function find (i,j,k:longint):longint; var o,x,now,l,r,mid:longint; begin len:=0; dec(i); while i>0 do begin inc(len); dl[len]:=-root[i]; i:=i-lowbit(i); end; while j>0 do begin inc(len); dl[len]:=root[j]; j:=j-lowbit(j); end; l:=1; r:=all; while l<>r do begin mid:=(l+r) div 2; now:=0; for i:=1 to len do begin o:=dl[i] div abs(dl[i]); x:=abs(dl[i]); now:=now+o*sum[left[x]]; end; if now<k then begin k:=k-now; for i:=1 to len do begin o:=dl[i] div abs(dl[i]); x:=abs(dl[i]); dl[i]:=right[x]*o; end; l:=mid+1; end else begin for i:=1 to len do begin o:=dl[i] div abs(dl[i]); x:=abs(dl[i]); dl[i]:=left[x]*o; end; r:=mid; end; end; exit(l); end; begin readln(n,m); for i:=1 to n do begin read(s[i]); dl[i]:=s[i]; end; readln; tot:=n; for i:=1 to m do begin read(que[i].t); if que[i].t='Q' then read(que[i].i,que[i].j,que[i].k) else begin read(que[i].i,que[i].j); inc(tot); dl[tot]:=que[i].j; end; readln; end; qsort(1,tot); i:=1; while i<=tot do begin inc(all); new[all]:=dl[i]; while dl[i]=new[all] do inc(i); end; for i:=1 to n do s[i]:=convert(s[i]); for i:=1 to m do if que[i].t='C' then que[i].j:=convert(que[i].j); tot:=0; build(1,all,0); for i:=1 to n do insert(1,s[i],i); for i:=1 to m do if que[i].t='Q' then writeln(new[find(que[i].i,que[i].j,que[i].k)]) else begin insert(-1,s[que[i].i],que[i].i); insert(1,que[i].j,que[i].i); s[que[i].i]:=que[i].j end; end.