BZOJ 2527 [Poi2011]Meteors:整体二分
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2527
题意:
有n个国家和m个空间站,每个空间站都属于一个国家,一个国家可以有多个空间站,所有空间站按照顺序形成一个环,也就是说,m号空间站和1号空间站相邻。
现在,将会有k场流星雨降临,每一场流星雨都会给区间[li,ri]内的每个空间站带来ai单位的陨石,每个国家都有一个收集陨石的目标pi,即第i个国家需要收集pi单位的陨石。
询问:每个国家最早完成陨石收集目标是在第几场流星雨过后。
1<=n,m,k<=300000
题解:
整体二分。
将所有的国家一起二分。
对于当前的答案区间[l,r],先模拟下前mid场的流星雨,用树状数组维护。
再将已经超出目标pi的国家放到左边;把没达到目标的放在右边,并将这些国家的需求减去已经收集到的数量。
然后恢复刚才的流星雨,带上相应的国家,分别左右递归。
当访问到叶子节点的时候(即l==r),当前存的国家的答案即为l。
AC Code:
1 #include <iostream> 2 #include <stdio.h> 3 #include <string.h> 4 #include <vector> 5 #define MAX_N 300005 6 #define INF 100000000 7 8 using namespace std; 9 10 int n,m,t; 11 int ct[MAX_N]; 12 int nd[MAX_N]; 13 int L[MAX_N]; 14 int R[MAX_N]; 15 int a[MAX_N]; 16 int ans[MAX_N]; 17 long long sum[MAX_N]; 18 long long dat[MAX_N]; 19 vector<int> sp[MAX_N]; 20 21 void update(int k,int x) 22 { 23 while(k>0) 24 { 25 dat[k]+=x; 26 k-=k&-k; 27 } 28 } 29 30 long long query(int k) 31 { 32 long long sum=0; 33 while(k<=m) 34 { 35 sum+=dat[k]; 36 k+=k&-k; 37 } 38 return sum; 39 } 40 41 void section(int l,int r,int x) 42 { 43 update(r,x); 44 update(l-1,-x); 45 } 46 47 void meteor(int x,int f) 48 { 49 if(L[x]<=R[x]) section(L[x],R[x],a[x]*f); 50 else section(L[x],m,a[x]*f),section(1,R[x],a[x]*f); 51 } 52 53 void read() 54 { 55 scanf("%d%d",&n,&m); 56 for(int i=1;i<=m;i++) 57 { 58 scanf("%d",&ct[i]); 59 sp[ct[i]].push_back(i); 60 } 61 for(int i=1;i<=n;i++) 62 { 63 scanf("%d",&nd[i]); 64 } 65 scanf("%d",&t); 66 for(int i=1;i<=t;i++) 67 { 68 scanf("%d%d%d",&L[i],&R[i],&a[i]); 69 } 70 t++; 71 L[t]=1; R[t]=t; a[t]=INF; 72 } 73 74 void dfs(vector<int> v,int l,int r) 75 { 76 if(l==r) 77 { 78 for(int i=0;i<v.size();i++) 79 { 80 ans[v[i]]=l; 81 } 82 return; 83 } 84 vector<int> vl,vr; 85 int mid=(l+r)>>1; 86 for(int i=l;i<=mid;i++) 87 { 88 meteor(i,1); 89 } 90 for(int i=0;i<v.size();i++) 91 { 92 sum[v[i]]=0; 93 } 94 for(int i=0;i<v.size();i++) 95 { 96 for(int j=0;j<sp[v[i]].size() && sum[v[i]]<nd[v[i]];j++) 97 { 98 int temp=sp[v[i]][j]; 99 sum[v[i]]+=query(temp); 100 } 101 } 102 for(int i=0;i<v.size();i++) 103 { 104 if(sum[v[i]]>=nd[v[i]]) vl.push_back(v[i]); 105 else nd[v[i]]-=sum[v[i]],vr.push_back(v[i]); 106 } 107 for(int i=l;i<=mid;i++) 108 { 109 meteor(i,-1); 110 } 111 dfs(vl,l,mid); 112 dfs(vr,mid+1,r); 113 } 114 115 void solve() 116 { 117 memset(dat,0,sizeof(dat)); 118 vector<int> v; 119 for(int i=1;i<=n;i++) v.push_back(i); 120 dfs(v,1,t); 121 } 122 123 void print() 124 { 125 for(int i=1;i<=n;i++) 126 { 127 if(ans[i]==t) printf("NIE\n"); 128 else printf("%d\n",ans[i]); 129 } 130 } 131 132 int main() 133 { 134 read(); 135 solve(); 136 print(); 137 }