bzoj 3065: 带插入区间K小值(分块)
2016-04-07 13:33
411 查看
Description
从前有n只跳蚤排成一行做早操,每只跳蚤都有自己的一个弹跳力a[i]。跳蚤国王看着这些跳蚤国欣欣向荣的情景,感到非常高兴。这时跳蚤国王决定理性愉悦一下,查询区间k小值。他每次向它的随从伏特提出这样的问题: 从左往右第x个到第y个跳蚤中,a[i]第k小的值是多少。这可难不倒伏特,他在脑袋里使用函数式线段树前缀和的方法水掉了跳蚤国王的询问。
这时伏特发现有些跳蚤跳久了弹跳力会有变化,有的会增大,有的会减少。
这可难不倒伏特,他在脑袋里使用树状数组套线段树的方法水掉了跳蚤国王的询问。(orz 主席树)
这时伏特发现有些迟到的跳蚤会插入到这一行的某个位置上,他感到非常生气,因为……他不会做了。
请你帮一帮伏特吧。
快捷版题意:带插入、修改的区间k小值在线查询。
Input
第一行一个正整数n,表示原来有n只跳蚤排成一行做早操。第二行有n个用空格隔开的非负整数,从左至右代表每只跳蚤的弹跳力。
第三行一个正整数q,表示下面有多少个操作。
下面一共q行,一共三种操作对原序列的操作:(假设此时一共m只跳蚤)
1. Q x y k: 询问从左至右第x只跳蚤到从左至右第y只跳蚤中,弹跳力第k小的跳蚤的弹跳力是多少。
(1 <= x <= y <= m, 1 <= k <= y - x + 1)
2. M x val: 将从左至右第x只跳蚤的弹跳力改为val。
(1 <= x <= m)
3. I x val: 在从左至右第x只跳蚤的前面插入一只弹跳力为val的跳蚤。即插入后从左至右第x只跳蚤是我刚插入的跳蚤。
(1 <= x <= m + 1)
为了体现在线操作,设lastAns为上一次查询的时候程序输出的结果,如果之前没有查询过,则lastAns = 0。
则输入的时候实际是:
Q _x _y _k ------> 表示 Q _x^lastAns _y^lastAns _k^lastAns
M _x _val ------> 表示 M _x^lastAns _val^lastAns
I _x _val ------> 表示 I _x^lastAns _val^lastAns
简单来说就是操作中输入的整数都要异或上一次询问的结果进行解码。
(祝Pascal的同学早日转C++,就不提供pascal版的描述了。)
Output
对于每个询问输出回答,每行一个回答。Sample Input
1010 5 8 28 0 19 2 31 1 22
30
I 6 9
M 1 11
I 8 17
M 1 31
M 6 26
Q 2 7 6
I 23 30
M 31 7
I 22 27
M 26 18
Q 26 17 31
I 5 2
I 18 13
Q 3 3 3
I 27 19
Q 23 23 30
Q 5 13 5
I 3 0
M 15 27
Q 0 28 13
Q 3 29 11
M 2 8
Q 12 5 7
I 30 19
M 11 19
Q 17 8 29
M 29 4
Q 3 0 12
I 7 18
M 29 27
Sample Output
282
31
0
14
15
14
27
15
14
HINT
此题作为一个小小的研究来搞吧~做法有很多~不知道这题究竟有多少种做法。请自觉O(log^2n),我故意卡块状链表,块链A了的请受我深情一拜……
A掉的同学请在Discuss里面简要说下自己的做法吧~
原序列长度 <= 35000
插入个数 <= 35000,修改个数 <= 70000,查询个数 <= 70000 ,0 <= 每时每刻的权值 <= 70000
由于是OJ上的题,所以数据无梯度。为了防止卡OJ,本题只有4组数据。
[b]我写的是分块[/b]
#include<cmath> #include<cstdio> #include<algorithm> #define lla la; using namespace std; int read_p,read_ca; inline int read(){ read_p=0;read_ca=getchar(); while(read_ca<'0'||read_ca>'9') read_ca=getchar(); while(read_ca>='0'&&read_ca<='9') read_p=read_p*10+read_ca-48,read_ca=getchar(); return read_p; } struct tree{ int l,r,k; }t[41000000]; int n,m,a[300][2000],b,num,nnu,nm=0,la=0,s[300],ne[300],xc[300],mid,root[300]; char ch[10]; int i,j,x,c,l,r,lc,rc,li,ri; const int MA=70000; inline bool cmp(int a,int b){ return a<b; } inline void in(int &p,int x){ if (!p) p=++nm,t[nm].l=t[nm].r=t[nm].k=0; int o=p; int l=0,r=MA,mid; while(l<r){ t[o].k++; mid=l+r>>1; if (x<=mid){ if (!t[o].l) t[o].l=++nm,t[nm].l=t[nm].r=t[nm].k=0; o=t[o].l; r=mid; }else{ if (!t[o].r) t[o].r=++nm,t[nm].l=t[nm].r=t[nm].k=0; o=t[o].r; l=mid+1; } } t[o].k++; } inline void del(int p,int x){ int l=0,r=MA,mid; while(l<r){ t[p].k--; mid=l+r>>1; if (x<=mid) p=t[p].l,r=mid;else p=t[p].r,l=mid+1; } t[p].k--; } inline int ask(){ l=read();r=read();x=read(); l^=lla;r^=lla;x^=lla; lc=0;rc=0; for (li=0;li!=-1;li=ne[li]) if ((lc+=s[li])>=l) break; lc=l-lc+s[li]-1; for (ri=0;ri!=-1;ri=ne[ri]) if ((rc+=s[ri])>=r) break; rc=r-rc+s[ri]-1; int ll=0,rr=70000,mid,nu,rt=0; nnu=nm; for (i=0;i<num;i++) xc[i]=root[i]; if (li!=ri){ for (i=lc;i<s[li];i++) in(rt,a[li][i]); for (i=0;i<=rc;i++) in(rt,a[ri][i]); }else for (i=lc;i<=rc;i++) in(rt,a[li][i]); int k; l=0;r=MA; while(l<r){ mid=l+r>>1;k=0; if (li!=ri)for (int i=ne[li];i!=ri;i=ne[i]) k+=t[t[xc[i]].l].k;k+=t[t[rt].l].k; if (k>=x){ if (li!=ri)for (int i=ne[li];i!=ri;i=ne[i]) xc[i]=t[xc[i]].l;rt=t[rt].l; r=mid; }else{ x-=k; if (li!=ri)for (int i=ne[li];i!=ri;i=ne[i]) xc[i]=t[xc[i]].r;rt=t[rt].r; l=mid+1; } } nm=nnu; return l; } inline void change(){ x=read();c=read(); x^=lla;c^=lla; l=0; for (i=0;i!=-1;i=ne[i]) if ((l+=s[i])>=x) break; x=x-l+s[i]-1; del(root[i],a[i][x]); a[i][x]=c; in(root[i],c); } inline void in(){ x=read();c=read(); x^=lla;c^=lla; l=0; for (i=0;i!=-1;i=ne[i]){ l+=s[i]; if (l>=x||ne[i]==-1) break; } x-=l-s[i]+1; for (j=s[i];j>x;j--) a[i][j]=a[i][j-1]; s[i]++;a[i][x]=c; in(root[i],c); if (s[i]==2*b){ s[i]=s[num]=b; root[num]=0; for (j=0;j<b;j++) a[num][j]=a[i][j+b]; for (j=0;j<b;j++) del(root[i],a[num][j]),in(root[num],a[num][j]); ne[num]=ne[i];ne[i]=num; num++; } } inline int max(int a,int b){return a>b?a:b;} int main(){ /*freopen("a.in","r",stdin); freopen("a.out","w",stdout);*/ n=read(); b=600; num=(n+b-1)/b; for (int i=0;i<n;i++) a[i/b][i%b]=read(),in(root[i/b],a[i/b][i%b]); for (int i=0;i<num-1;i++) s[i]=b,ne[i]=i+1;s[num-1]=n-b*(num-1); ne[num-1]=-1; m=read(); while(m--){ scanf("%s",ch); if (ch[0]=='Q') printf("%d\n",la=ask());else if (ch[0]=='M') change();else in(); } }
View Code
相关文章推荐
- Web Service
- 基于redis缓存的session共享
- 多线程售票程序
- 浅谈 script 加载
- tomcat 中配置 access log
- mysql命令行导出数据库
- ubuntu14.04如何使用google search
- HTML5第一讲
- 第5周心得
- 第三次作业,问卷调查
- 调用API自动配置zabbix version 3.0
- cocos2d-x 常规库的图文件配置
- 读深入C++对象模型的总结
- CodeForces - 584A Olesya and Rodion (模拟)水
- Bitmap大小压缩的理解
- $this->assign(); 与 $this->display(); PHP
- synonyms
- Ali RocketMQ与Kafka对比
- 第四次作业——计算器(实现“+ - * /”)
- C++三元运算符?: