1. 程式人生 > >BZOJ 2527 [POI2011]MET-Meteors (整體二分+樹狀陣列)

BZOJ 2527 [POI2011]MET-Meteors (整體二分+樹狀陣列)

題目大意:略

洛谷傳送門

整體二分裸題

考慮只有一個國家的情況如何處理

對詢問數量二分答案,暴力$O(m)$打差分,求字首和驗證,時間是$O(mlogK)$

如果有$n$個國家,就是$O(nmlogK)$,非常不優秀的時間複雜度

發現我們對於每個國家都進行一次二分很浪費時間

考慮把國家分成一定數量的集合

每次二分出一個答案$mid$

把集合內的國家按照能否滿足要求分成兩個集合$S1,S2$

如果能滿足要求,當前詢問的mid不一定是最優解,答案範圍一定是$[l,mid]$

如果不能滿足要求,當前$mid$不能作為答案,答案範圍只能是$[mid+1,r]$

$(l,mid,S1),(mid+1,r,S2)$遞迴分治處理,用樹狀陣列維護即可

時間$O((K+n)logKlogm)$

 1 #include <vector>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <algorithm>
 5 #define N1 300100
 6 #define ll long long
 7 #define dd double
 8 #define inf 233333333
 9 using namespace std;
10 
11 int gint()
12 {
13     int ret=0,fh=1
;char c=getchar(); 14 while(c<'0'||c>'9'){if(c=='-')fh=-1;c=getchar();} 15 while(c>='0'&&c<='9'){ret=ret*10+c-'0';c=getchar();} 16 return ret*fh; 17 } 18 int n,m,Q,K; 19 struct BIT{ 20 ll sum[N1]; 21 void update(int x,int w){ for(int i=x;i<=m;i+=(i&(-i))) sum[i]+=w; }
22 ll query(int x){ ll ans=0; for(int i=x;i;i-=(i&(-i))) ans+=sum[i]; return ans; } 23 void clr(int x){ for(int i=x;i<=m;i+=(i&(-i))) sum[i]=0; } 24 }s; 25 struct node{int l,r,w;}q[N1]; 26 vector<int>son[N1]; 27 int que[N1*3],tl,ans[N1],id[N1],tmp[N1],p[N1]; 28 void alldic(int l,int r,int ql,int qr) 29 { 30 if(l>r||ql>qr) return; 31 int qmid=(ql+qr)>>1,i,j,x,S=l,E=r; ll res; 32 for(i=ql;i<=qmid;i++) 33 { 34 if(q[i].l<=q[i].r){ 35 s.update(q[i].l,q[i].w); s.update(q[i].r+1,-q[i].w); 36 que[++tl]=q[i].l; que[++tl]=q[i].r+1; 37 }else{ 38 s.update(q[i].l,q[i].w); s.update(1,q[i].w); s.update(q[i].r+1,-q[i].w); 39 que[++tl]=1; que[++tl]=q[i].l; que[++tl]=q[i].r+1; 40 } 41 } 42 for(i=l;i<=r;i++) 43 { 44 x=id[i]; res=p[x]; 45 for(j=0;j<son[x].size();j++) 46 { 47 res-=s.query(son[x][j]); 48 if(res<=0) { ans[x]=qmid; tmp[S++]=x; break;} 49 } 50 if(res>0) { p[x]=res; tmp[E--]=x; } 51 } 52 for(i=l;i<=r;i++) id[i]=tmp[i]; 53 while(tl) s.clr(que[tl--]); 54 alldic(l,S-1,ql,qmid-1); alldic(E+1,r,qmid+1,qr); 55 } 56 57 int main() 58 { 59 scanf("%d%d",&n,&m); 60 int i,j,k,x,y,z; 61 for(i=1;i<=m;i++){ x=gint(),son[x].push_back(i); } 62 for(i=1;i<=n;i++){ p[i]=gint(); id[i]=i;} 63 scanf("%d",&Q); 64 for(i=1;i<=Q;i++){ q[i].l=gint(); q[i].r=gint(); q[i].w=gint(); } 65 alldic(1,n,1,Q); 66 for(i=1;i<=n;i++) 67 { 68 if(!ans[i]) puts("NIE"); 69 else printf("%d\n",ans[i]); 70 } 71 return 0; 72 }