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 }

 

posted @ 2017-12-06 17:59  Leohh  阅读(156)  评论(0编辑  收藏  举报