【BZOJ3110】K大数查询(ZJOI2013)-整体二分+线段树
来源:互联网 发布:腾讯视频2017网络剧 编辑:程序博客网 时间:2024/05/16 15:59
测试地址:K大数查询
做法:这题需要用到整体二分和线段树(这题也可以用树套树做,然而复杂度就很恶心了)。
这一题由于一个位置可以有多个数,所以看上去束手无策,然而这一题并不强制在线,所以我们自然想到整体二分。
因为一个区间内比一个数大的数单调,所以这个性质是可二分的,所以函数
以下是本人代码(91分WA,原因待探究):
#include <cstdio>#include <cstdlib>#include <cstring>#include <iostream>#include <algorithm>#define inf 1000000000#define ll long longusing namespace std;int n,m,ans[50010],tmp[50010],qcnt=0;ll p[200010]={0},seg[200010]={0},Min=inf,Max=-inf;struct query{ int op,a,b,id; ll cur,c;}q[50010],a1[50010],a2[50010];void add(int no,int l,int r,int s,int t,int val){ if (l>=s&&r<=t) { p[no]+=val; seg[no]+=(r-l+1)*val; return; } int mid=(l+r)>>1; if (p[no]!=0) { p[no<<1]+=p[no],p[no<<1|1]+=p[no]; seg[no<<1]+=(mid-l+1)*p[no],seg[no<<1|1]+=(r-mid)*p[no]; p[no]=0; } if (s<=mid) add(no<<1,l,mid,s,t,val); if (t>mid) add(no<<1|1,mid+1,r,s,t,val); seg[no]=seg[no<<1]+seg[no<<1|1];}ll query(int no,int l,int r,int s,int t){ if (l>=s&&r<=t) return seg[no]; int mid=(l+r)>>1;ll tot=0; if (p[no]!=0) { p[no<<1]+=p[no],p[no<<1|1]+=p[no]; seg[no<<1]+=(mid-l+1)*p[no],seg[no<<1|1]+=(r-mid)*p[no]; p[no]=0; } if (s<=mid) tot+=query(no<<1,l,mid,s,t); if (t>mid) tot+=query(no<<1|1,mid+1,r,s,t); return tot;}void solve(int s,int t,int l,int r){ if (s>t||l>r) return; if (l==r) { for(int i=s;i<=t;i++) if (q[i].op==2) ans[q[i].id]=l; return; } int mid=(l+r)>>1; mid++; for(int i=s;i<=t;i++) { if (q[i].op==1&&q[i].c>=mid) add(1,1,n,q[i].a,q[i].b,1); if (q[i].op==2) tmp[q[i].id]=query(1,1,n,q[i].a,q[i].b); } for(int i=s;i<=t;i++) if (q[i].op==1&&q[i].c>=mid) add(1,1,n,q[i].a,q[i].b,-1); int n1=0,n2=0; for(int i=s;i<=t;i++) { if (q[i].op==2) { if (q[i].cur+tmp[q[i].id]>=q[i].c) a2[++n2]=q[i]; else { q[i].cur+=tmp[q[i].id]; a1[++n1]=q[i]; } } else { if (q[i].c<mid) a1[++n1]=q[i]; else a2[++n2]=q[i]; } } for(int i=1;i<=n1;i++) q[s+i-1]=a1[i]; for(int i=1;i<=n2;i++) q[s+n1+i-1]=a2[i]; solve(s,s+n1-1,l,mid-1); solve(s+n1,t,mid,r);}int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=m;i++) { scanf("%d%d%d%lld",&q[i].op,&q[i].a,&q[i].b,&q[i].c); if (q[i].op==2) q[i].cur=0,q[i].id=++qcnt; else Min=min(Min,q[i].c),Max=max(Max,q[i].c); } solve(1,m,Min,Max); for(int i=1;i<=qcnt;i++) printf("%d\n",ans[i]); return 0;}
0 0
- 【BZOJ3110】K大数查询(ZJOI2013)-整体二分+线段树
- [BZOJ3110][Zjoi2013]K大数查询(主席树套线段树||整体二分 )
- [整体二分] BZOJ3110: [Zjoi2013]K大数查询
- bzoj3110 K大数查询(整体二分+线段树)
- [BZOJ3110][ZJOI2013]K大数查询-CDQ分治-整体二分
- BZOJ_P3110 [ZJOI2013]K大数查询(线段树+整体二分)
- [BZOJ]3110: [Zjoi2013]K大数查询 整体二分+线段树
- bzoj3110[Zjoi2013]K大数查询 主席树套线段树
- [BZOJ3110][ZJOI2013]K大数查询(线段树套线段树)
- bzoj3110: [Zjoi2013]K大数查询 树套数
- 【整体二分+树状数组区间加区间和】BZOJ3110 [Zjoi2013]K大数查询
- bzoj3110 k大数查询 zjoi2013
- 【ZJOI2013】【BZOJ3110】K大数查询
- [BZOJ3110][Zjoi2013]K大数查询
- [BZOJ3110][Zjoi2013]K大数查询
- 【BZOJ3110】【ZJOI2013】K大数查询
- bzoj3110【ZJOI2013】K大数查询
- 【ZJOI2013&&BZOJ3110】K大数查询
- linux总结07-Ubuntu操作系统root账户密码设置
- C++函数之函数模板浅析
- notepad++插件NppFTPa以及安装vsftpd相关配置
- 教你初步了解红黑树
- 归纳迁移学习算法---Adaboost 算法实例解析四
- 【BZOJ3110】K大数查询(ZJOI2013)-整体二分+线段树
- PAT 1049.数列的片段和
- 哪些中药最清肝明目 这4味中药最牛
- View如何加载到窗口
- 老夏书单第一弹——吉祥纹莲花楼
- 使用字符映射完成简单的对称加密
- floyg最短路径算法
- 雷神:视音频数据处理入门——001
- HDU6030-Happy Necklace