Bzoj2527--Poi2011Meteor
整体二分的题
以前没有写过整体二分的题,感受了一下
大概是把答案和所有的询问一同二分,就是把满足当前二分区间的询问和不满足的分开后递归下去
复杂度由主定理保证,里面的复杂度必须是之和二分后的区间线性相关,而不是与整个区间相关,复杂度才有保证
有点cdq的感觉
代码 :
#include<bits/stdc++.h> #define LL long long using namespace std; #define INF 1000000000 #define MAXN 300005 int n,m,t,id[MAXN],Ml[MAXN],Mr[MAXN],A[MAXN],mis[MAXN]; int head[MAXN],to[MAXN*2]; int ans[MAXN]; namespace SegmentTree{ const int L=0,R=1; struct node{ int son[2];LL add; }x[MAXN*2]; int sz=1; void _init(int l,int r,int num) { if(l==r) return; int mid=l+r>>1; x[num].son[L]=++sz;x[num].son[R]=++sz; _init(l,mid,x[num].son[L]); _init(mid+1,r,x[num].son[R]); } void Add(int l,int r,int nl,int nr,int num,int v) { if(l==nl&&r==nr) {x[num].add+=v;return;} int mid=nl+nr>>1; if(l>mid) Add(l,r,mid+1,nr,x[num].son[R],v); else if(r<=mid) Add(l,r,nl,mid,x[num].son[L],v); else { Add(l,mid,nl,mid,x[num].son[L],v); Add(mid+1,r,mid+1,nr,x[num].son[R],v); } } LL Qurey(int pos,int l,int r,int num) { if(l==r) return x[num].add; int mid=l+r>>1; if(pos<=mid) return Qurey(pos,l,mid,x[num].son[L])+x[num].add; else return Qurey(pos,mid+1,r,x[num].son[R])+x[num].add; } } #define ST SegmentTree bool f[MAXN]; void solve(int l,int r,int L,int R) { if(l>r) return; if(L==R) { for(int i=l;i<=r;i++) ans[id[i]]=L; return; } int mid=L+R>>1; for(int i=L;i<=mid;i++) { if(Ml[i]<=Mr[i]) ST::Add(Ml[i],Mr[i],1,m,1,A[i]); else { ST::Add(Ml[i],m,1,m,1,A[i]); ST::Add(1,Mr[i],1,m,1,A[i]); } } for(int i=l;i<=r;i++) { LL get=0; for(int j=head[id[i]];j;j=to[j]) { get+=ST::Qurey(j,1,m,1); if(get>=mis[id[i]]) break; } if(get<mis[id[i]]) f[id[i]]=1,mis[id[i]]-=get; } int p1=l,p2=r; while(p2>p1) { while(p2>p1&&!f[id[p1]]) p1++; while(p2>p1&&f[id[p2]]) p2--; if(p2>p1) swap(id[p1],id[p2]); } p1=l-1; for(int i=l;i<=r;i++) {if(!f[id[i]]) p1=i;f[id[i]]=0;} for(int i=L;i<=mid;i++) { if(Ml[i]<=Mr[i]) ST::Add(Ml[i],Mr[i],1,m,1,-A[i]); else { ST::Add(Ml[i],m,1,m,1,-A[i]); ST::Add(1,Mr[i],1,m,1,-A[i]); } } solve(l,p1,L,mid);solve(p1+1,r,mid+1,R); } int main() { scanf("%d%d",&n,&m); for(int a,i=1;i<=m;i++) { scanf("%d",&a); to[i]=head[a];head[a]=i; } for(int i=1;i<=n;i++) { scanf("%d",&mis[i]);id[i]=i; } scanf("%d",&t); for(int i=1;i<=t;i++) { scanf("%d%d%d",&Ml[i],&Mr[i],&A[i]); } A[++t]=INF;Ml[t]=1;Mr[t]=m; ST::_init(1,m,1); solve(1,n,1,t); for(int i=1;i<=n;i++) { if(ans[i]==t) puts("NIE"); else printf("%d\n",ans[i]); } return 0; } #undef ST