BZOJ 2527: [Poi2011]Meteors [整体二分]
题意:
一个星球环形带上分为 $M$ 个区域,$n$个国家,$k$天,每个区域可能有若干国家的陨石收集器,每一天有一段连续区域下陨石雨,
其上所有收集器都为本国家收集到 $D_i$ 的陨石,每个国家有一定的陨石需求量$P_i$,求每个国家第几天收集陨石量恰好满足需求
$1 \le n,m,k \le 3∗10^5\quad 1 \le A_i,P_i < 10^9$
整体二分
$zyz:$整体二分是在权值上进行$CDQ$分治
我觉得更像是说$:$整体二分是在答案上进行$CDQ$分治
整体二分是二分答案在数据结构题上的扩展
因为数据结构题二分的答案通常是第几个操作之后,需要进行哪些操作之后才能判断
核心就是维护一个$cur$数组保存当前的影响
$Sol(l,r,S)\ l,r$是当前
操作$[l,mid]$的影响(对答案的贡献),加上$cur$看看与询问相比大小分成左右递归分治
询问集合保存编号就好了
是不是命名有点奇怪,q是操作,a是询问。。。所以说无视这份代码吧
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> using namespace std; #define lc x<<1 #define rc x<<1|1 #define lson x<<1,l,mid #define rson x<<1|1,mid+1,r const int N=3e5+5,INF=1e9; typedef long long ll; inline int read(){ char c=getchar();int x=0,f=1; while(c<'0'||c>'9'){if(c=='-')f=-1; c=getchar();} while(c>='0'&&c<='9'){x=x*10+c-'0'; c=getchar();} return x*f; } int n,m,k; struct edge{ int v,ne; }e[N]; int h[N],cnt; inline void ins(int u,int v){ cnt++; e[cnt].v=v;e[cnt].ne=h[u];h[u]=cnt; } int a[N],t1[N],t2[N],lim[N]; struct Meteor{ int l,r,w; }q[N]; ll c[N]; inline int lowbit(int x){return x&-x;} inline void _add(int p,ll v){for(;p<=m;p+=lowbit(p)) c[p]+=v;} inline ll sum(int p){ ll re=0; for(;p;p-=lowbit(p)) re+=c[p]; return re; } inline void add(int l,int r,int v){ _add(l,v);_add(r+1,-v); } ll cur[N]; int ans[N]; void Sol(int l,int r,int sl,int sr){//printf("Sol %d %d %d %d\n",l,r,sl,sr); if(sl>sr) return; if(l==r){ for(int i=sl;i<=sr;i++) ans[a[i]]=l; return; } int mid=(l+r)>>1; for(int i=l;i<=mid;i++){ if(q[i].l<=q[i].r) add(q[i].l,q[i].r,q[i].w); else add(1,q[i].r,q[i].w),add(q[i].l,m,q[i].w); } int p1=0,p2=0; for(int i=sl;i<=sr;i++){ int u=a[i];ll s=cur[u],p=lim[u]; for(int k=h[u];k;k=e[k].ne) if((s+=sum(e[k].v))>=p) break; if(s>=p) t1[++p1]=u; else t2[++p2]=u,cur[u]=s; } for(int i=l;i<=mid;i++){ if(q[i].l<=q[i].r) add(q[i].l,q[i].r,-q[i].w); else add(1,q[i].r,-q[i].w),add(q[i].l,m,-q[i].w); } for(int i=1;i<=p1;i++) a[sl+i-1]=t1[i]; for(int i=1;i<=p2;i++) a[sl+p1+i-1]=t2[i]; Sol(l,mid,sl,sl+p1-1); Sol(mid+1,r,sl+p1,sr); } int main(){ freopen("in","r",stdin); n=read();m=read(); for(int i=1;i<=m;i++) ins(read(),i); for(int i=1;i<=n;i++) lim[i]=read(),a[i]=i; k=read(); for(int i=1;i<=k;i++) q[i].l=read(),q[i].r=read(),q[i].w=read(); q[++k].l=1;q[k].r=m;q[k].w=INF; Sol(1,k,1,n); //for(int i=1;i<=n;i++) printf("%d %d %lld\n",i,ans[i],cur[i]); for(int i=1;i<=n;i++){ if(ans[i]!=k) printf("%d\n",ans[i]); else puts("NIE"); } }
Copyright:http://www.cnblogs.com/candy99/