bzoj3110 K大数查询(整体二分+线段树)
来源:互联网 发布:卡二的网络不好 编辑:程序博客网 时间:2024/05/16 20:30
整体二分
①将修改和查询看做是一条队列。
②二分一个答案Mid,然后扫一下队列,用数据结构来依次(依照操作和询问顺序地)维护修改权值小于或等于Mid的修改对每个查询的贡献。
③将数据结构清空。(注意时间复杂度)
④将修改和询问分成两份,其中
询问:如果问题答案小于或等于Mid,就放在队列1。
如果问题答案大于Mid,修改询问(减掉小于或等于Mid的问题对本答案的贡献),然后放在队列2。
修改:如果修改权值大于或等于Mid,就放在队列1,否则放在队列2。
⑤递归往下做。
程序
#include <iostream>#include <algorithm>#include <string.h>#include <string>#include <cmath>#include <stdio.h>#include <stdlib.h>#include <vector>using namespace std;struct Query{ int q,L,R,v,e;}q[50100],p1[50100],p2[50100];int T[201000],ad[201000],no[50100],ans[50100],n,m;void down(int ro,int L,int R) { int mid=(L+R)>>1,zuo=ro<<1,you=zuo+1; T[zuo]+=(mid-L+1)*ad[ro];ad[zuo]+=ad[ro]; T[you]+=(R-mid)*ad[ro];ad[you]+=ad[ro]; ad[ro]=0;}void update(int ro,int L,int R,int le,int ri) { if (le<=L&&R<=ri) { T[ro]+=R-L+1; ad[ro]++; return ; } if (L>ri||R<le) return; if (ad[ro]) down(ro,L,R); int mid=(L+R)>>1,zuo=ro<<1,you=zuo+1; update(zuo,L,mid,le,ri);update(you,mid+1,R,le,ri); T[ro]=T[zuo]+T[you];}int query(int ro,int L,int R,int le,int ri) { if (le<=L&&R<=ri) return T[ro]; if (L>ri||R<le) return 0; if (ad[ro]) down(ro,L,R); int mid=(L+R)>>1,zuo=ro<<1,you=zuo+1; return query(zuo,L,mid,le,ri)+query(you,mid+1,R,le,ri);}void build(int ro,int L,int R) { if (T[ro]==0) return; if (L==R) {T[ro]=ad[ro]=0;return;} int mid=(L+R)>>1,zuo=ro<<1,you=zuo+1; build(zuo,L,mid);build(you,mid+1,R); T[ro]=ad[ro]=0;}void solve(int he,int ta,int L,int R) { if (ta<he) return; if (L==R) { for (int i=he;i<=ta;i++) if (q[i].q==2) ans[q[i].e]=L; return ; } int mid=L+R>>1; for (int i=he;i<=ta;i++) { if (q[i].q==1&&q[i].v<=mid) update(1,1,n,q[i].L,q[i].R); else if (q[i].q==2) no[i]=query(1,1,n,q[i].L,q[i].R); } build(1,1,n); int cnt1=0,cnt2=0; for (int i=he;i<=ta;i++) if (q[i].q==1) if (q[i].v<=mid) p1[++cnt1]=q[i]; else p2[++cnt2]=q[i]; else if (no[i]>=q[i].v) p1[++cnt1]=q[i]; else {q[i].v-=no[i];p2[++cnt2]=q[i];} for (int i=1;i<=cnt1;i++) q[i+he-1]=p1[i]; for (int i=1;i<=cnt2;i++) q[he+cnt1+i-1]=p2[i]; solve(he,he+cnt1-1,L,mid); solve(he+cnt1,ta,mid+1,R);}int main(){ scanf("%d%d",&n,&m); for (int i=1;i<=m;i++){ int x,y,z,w; scanf("%d%d%d%d",&x,&y,&z,&w); if (x==1)w=-w; q[i] = (Query) {x,y,z,w,i}; } for (int i=1;i<=m;i++) ans[i]=-60000; solve(1,m,-50100,50100); for (int i=1;i<=m;i++) if (ans[i]!=-60000) { if (ans[i]==1) printf("50000\n"); else printf("%d\n",-ans[i]); } return 0;}
推荐看
http://www.cnblogs.com/dirge/p/5810855.html
Jeanne d’Arc镇楼
阅读全文
0 0
- 【BZOJ3110】K大数查询(ZJOI2013)-整体二分+线段树
- bzoj3110 K大数查询(整体二分+线段树)
- [BZOJ3110][Zjoi2013]K大数查询(主席树套线段树||整体二分 )
- [整体二分] BZOJ3110: [Zjoi2013]K大数查询
- BZOJ3110 K大数查询 【线段树 + 整体二分 或 树套树(非正解)】
- 【整体二分】[ZJOI 2013] bzoj3110 K大数查询
- [ZJOI 2013] bzoj3110 K大数查询 (整体二分)
- bzoj3110 K大数查询 整体二分&树状数组
- [BZOJ3110][ZJOI2013]K大数查询-CDQ分治-整体二分
- BZOJ_P3110 [ZJOI2013]K大数查询(线段树+整体二分)
- K大数查询——整体二分套线段树
- [BZOJ]3110: [Zjoi2013]K大数查询 整体二分+线段树
- [BZOJ3110]K大数查询|线段树套线段树
- bzoj3110[Zjoi2013]K大数查询 主席树套线段树
- [BZOJ3110][ZJOI2013]K大数查询(线段树套线段树)
- 【整体二分+树状数组区间加区间和】BZOJ3110 [Zjoi2013]K大数查询
- bzoj3110 K大数查询
- [bzoj3110]K大数查询
- 假设你有一个各位数字互不相同的四位数,把所有的数字从大到小排序后得到a,从小到大后得到b,然后用a-b替换原来这个数,并且继续操作。例如,从1234出发,依次可以得到4321-1234=3087、87
- Android音频系统之音频框架
- AtCoder:Connected?(思维)
- 关于Python的一些学习资料总结
- gradle包含库出现问题
- bzoj3110 K大数查询(整体二分+线段树)
- EasyX鼠标函数和MBCS、Unicode编码
- Django使用mysql操作实战系列之七
- arrayQueue 和linkedQueue
- tomcat集群--整合Apache服务器,采用mod_proxy连接模式
- apk签名之用 jarsigner签名
- mySQL 截取小数
- Sql性能检测工具:Sql server profiler和优化工具:Database Engine Tuning Advisor
- Android系统进程间通信(IPC)机制Binder中的Server启动过程源代码分析