[BZOJ3110][Zjoi2013]K大数查询(主席树套线段树||整体二分 )
2016-04-28 09:57
561 查看
题目描述
传送门题解
外层权值线段树,权值线段树的每一个位置都是一棵线段树,线段树用动态开点。注意pushdown或者查询的时候还有可能要继续开点。
注意最顶端的点的权有可能是炸了int了,因为有可能加入了50000^2个点。
update 2017.1.9
整体二分第一题
代码
#include<algorithm> #include<iostream> #include<cstring> #include<cstdio> using namespace std; #define LL long long const int max_n=1e6+5; const int max_tree=2e7+5; int n,m,opt,cnt,N,t,ans,sz; int A[max_n],B[max_n],C[max_n],number[max_n],hash[max_n];bool flag[max_n]; int root[max_n],ls[max_tree],rs[max_tree]; LL sum[max_tree],delta[max_tree]; inline int find(int x){ int l=1,r=N,mid; while (l<=r){ mid=(l+r)>>1; if (x>hash[mid]) l=mid+1; else r=mid-1; } return l; } inline void modify(int now){ sum[now]=sum[ls[now]]+sum[rs[now]]; } inline void pushdown(int now,int l,int r,int mid){ if (delta[now]){ if (!ls[now]) ls[now]=++sz; sum[ls[now]]+=delta[now]*(mid-l+1); delta[ls[now]]+=delta[now]; if (!rs[now]) rs[now]=++sz; sum[rs[now]]+=delta[now]*(r-mid); delta[rs[now]]+=delta[now]; delta[now]=0; } } inline void update(int last,int &now,int l,int r,int lrange,int rrange,LL v){ int mid=(l+r)>>1; if (!now) now=++sz; ls[now]=ls[last]; rs[now]=rs[last]; if (lrange<=l&&r<=rrange){ sum[now]+=v*(r-l+1); delta[now]+=v; return; } pushdown(now,l,r,mid); if (lrange<=mid) update(ls[last],ls[now],l,mid,lrange,rrange,v); if (mid+1<=rrange) update(rs[last],rs[now],mid+1,r,lrange,rrange,v); modify(now); } inline LL query(int now,int l,int r,int lrange,int rrange){ int mid=(l+r)>>1;LL ans=0; if (lrange<=l&&r<=rrange) return sum[now]; pushdown(now,l,r,mid); if (lrange<=mid) ans+=query(ls[now],l,mid,lrange,rrange); if (mid+1<=rrange) ans+=query(rs[now],mid+1,r,lrange,rrange); return ans; } inline void v_update(int now,int l,int r,int x,int lrange,int rrange){ int mid=(l+r)>>1; update(root[now],root[now],1,n,lrange,rrange,1); if (l==r) return; if (x<=mid) v_update(now<<1,l,mid,x,lrange,rrange); else v_update(now<<1|1,mid+1,r,x,lrange,rrange); } inline int v_query(int now,int l,int r,int lrange,int rrange,LL k){ if (!now) return 0; int mid=(l+r)>>1; if (l==r) return l; LL t=query(root[now<<1],1,n,lrange,rrange); if (t>=k) return v_query(now<<1,l,mid,lrange,rrange,k); else return v_query(now<<1|1,mid+1,r,lrange,rrange,k-t); } int main(){ scanf("%d%d",&n,&m); for (int i=1;i<=m;++i){ scanf("%d%d%d%d",&opt,&A[i],&B[i],&C[i]); if (opt==1) flag[i]=true,number[++cnt]=C[i]; } sort(number+1,number+cnt+1); for (int i=1;i<=cnt;++i) if (number[i]!=number[i-1]) hash[++N]=number[i]; for (int i=1;i<=m;++i) if (flag[i]){ t=find(C[i]); v_update(1,1,N,t,A[i],B[i]); } else{ LL tot=query(root[1],1,n,A[i],B[i]); LL t=(LL)tot-(LL)C[i]+1; ans=v_query(1,1,N,A[i],B[i],t); printf("%d\n",hash[ans]); } }
#include<algorithm> #include<iostream> #include<cstring> #include<cstdio> #include<cmath> using namespace std; #define N 50005 #define LL long long int n,m; struct hp{int ord,l,r,x,id,num;}opt ; LL sum[N*4],delta[N*4]; bool cover[N*4]; int ans ; void update(int now) { sum[now]=sum[now<<1]+sum[now<<1|1]; } void pushdown(int now,int l,int r,int mid) { if (cover[now]) { sum[now<<1]=sum[now<<1|1]=0; delta[now<<1]=delta[now<<1|1]=0; cover[now<<1]=cover[now<<1|1]=1; cover[now]=0; } if (delta[now]) { sum[now<<1]+=delta[now]*(LL)(mid-l+1);delta[now<<1]+=delta[now]; sum[now<<1|1]+=delta[now]*(LL)(r-mid);delta[now<<1|1]+=delta[now]; delta[now]=0; } } void change(int now,int l,int r,int lr,int rr) { int mid=(l+r)>>1; if (lr<=l&&r<=rr) { sum[now]+=(LL)(r-l+1); ++delta[now]; return; } pushdown(now,l,r,mid); if (lr<=mid) change(now<<1,l,mid,lr,rr); if (mid+1<=rr) change(now<<1|1,mid+1,r,lr,rr); update(now); } LL query(int now,int l,int r,int lr,int rr) { int mid=(l+r)>>1;LL ans=0; if (lr<=l&&r<=rr) return sum[now]; pushdown(now,l,r,mid); if (lr<=mid) ans+=query(now<<1,l,mid,lr,rr); if (mid+1<=rr) ans+=query(now<<1|1,mid+1,r,lr,rr); return ans; } int cmp(hp a,hp b) { return a.num<b.num; } void dvd(int l,int r,int a,int b) { if (l==r) { for (int i=a;i<=b;++i) if (opt[i].ord==2) ans[opt[i].id]=l; return; } int mid=(l+r)>>1; int pa=0,pb=b-a+1; sum[1]=delta[1]=0; cover[1]=1; for (int i=a;i<=b;++i) { if (opt[i].ord==1) { if (opt[i].x<=mid) opt[i].num=++pa; else { change(1,1,n,opt[i].l,opt[i].r); opt[i].num=++pb; } } else { LL t=query(1,1,n,opt[i].l,opt[i].r); if (t>=opt[i].x) opt[i].num=++pb; else { opt[i].x-=t; opt[i].num=++pa; } } } sort(opt+a,opt+b+1,cmp); dvd(l,mid,a,a+pa-1); dvd(mid+1,r,a+pa,b); } int cmpid(hp a,hp b) { return a.id<b.id; } int main() { scanf("%d%d",&n,&m); for (int i=1;i<=m;++i) { scanf("%d%d%d%d",&opt[i].ord,&opt[i].l,&opt[i].r,&opt[i].x); opt[i].id=i; } dvd(0,n,1,m); sort(opt+1,opt+m+1,cmpid); for (int i=1;i<=m;++i) if (opt[i].ord==2) printf("%d\n",ans[i]); }
总结
这种动态开点点数和空间的计算十分蛋疼。相关文章推荐
- Win8如何禁用Power键?Win8禁用电脑上Power键方法
- Hadoop 配置本篇主要就是配置HDFS和YARN
- LoadRunner中Java Vuser协议脚本开发
- 浅谈:无处不在的二分(1)
- apache对象池的使用
- js小技巧
- redis+cookies实现session机制(解决 手机浏览器不自动回传cookies导致session不可用问题)
- mysql的下载到安装使用
- 机器学习课堂笔记(十二)
- 学习整理——以太帧、ip帧、udp/tcp帧、http报文结构
- jbpm-6.3.0.Final-installer-full在Windows上的部署、数据库由H2切换为MySql、Linux上的部署全过程
- ssh org.springframework.dao.InvalidDataAccessResourceUsageException: could not execute query; neste
- [BZOJ2882]2882: 工艺
- C语言链表的基础练习
- BigTable
- iOS开发 ☞ 应用间跳转
- 初始python
- Ubuntu系统操作快捷键
- 引用js文件
- mysql ab复制