[POI2011]MET-Meteors(整体二分+树状数组)

题意

给定一个环,每个节点有一个所属国家,k次事件,每次对[l,r]区间上的每个点点权加上一个值,求每个国家最早多少次操作之后所有点的点权和能达到一个值

题解

一个一个国家算会T。
这题要用整体二分。我们二分mid给所有国家判断。把可以满足条件的国家放在左边,把所有不满足的国家放在右边。然后继续递归。
本题要求区间加减单点查询。所以套树状数组维护。

 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdio>
 4 #include<cmath>
 5 #include<algorithm>
 6 #include<vector>
 7 using namespace std;
 8 const long long N=300010;
 9 const long long INF=1e9+1;
10 vector<long long> belong[N];
11 long long c[N];
12 long long n,m,target[N],con[N],ls[N],rs[N],val[N],ans[N],k;
13 long long now,LL[N],RR[N],sum[N];
14 long long lowbit(long long x){
15     return x&-x;
16 }
17 void add(long long x,long long w){
18     for(long long i=x;i<=m;i+=lowbit(i)){
19         c[i]+=w;
20     }
21 }
22 long long check(long long x){
23     long long tmp=0;
24     for(long long i=x;i>=1;i-=lowbit(i)){
25         tmp+=c[i];
26     }
27     return tmp;
28 }
29 void change(long long l,long long r,long long w){
30     if(l<=r){
31         add(l,w);add(r+1,-w);
32     } 
33     else {
34         add(l,w);add(m+1,-w);
35         add(1,w);add(r+1,-w);
36     }
37 }
38 void query(long long l,long long r,long long L,long long R){
39     if(l>r)return ;
40     if(L>R)return ;
41     if(l==r){
42         for(long long i=L;i<=R;i++){
43             ans[con[i]]=l;
44         }
45         return;
46     }
47     long long mid=l+r>>1;
48     while(now<mid){
49         now++;
50         change(ls[now],rs[now],val[now]);
51     }
52     while(now>mid){
53         change(ls[now],rs[now],-val[now]);
54         now--;
55     }
56     for(long long i=L;i<=R;i++){
57         sum[con[i]]=0;
58         for(long long j=0;j<belong[con[i]].size();j++){
59             sum[con[i]]+=check(belong[con[i]][j]);
60             if(sum[con[i]]>target[con[i]])break;
61         }
62     }
63     long long rcnt=0;long long lcnt=0;
64     for(long long i=L;i<=R;i++){
65         if(sum[con[i]]>=target[con[i]])LL[++lcnt]=con[i];
66         else RR[++rcnt]=con[i];
67     }
68     for(long long i=1;i<=lcnt;i++)con[i+L-1]=LL[i];
69     for(long long i=1;i<=rcnt;i++)con[i+L-1+lcnt]=RR[i];
70     query(l,mid,L,L+lcnt-1);
71     query(mid+1,r,L+lcnt,R);
72 }
73 int main(){
74     scanf("%lld%lld",&n,&m);
75     for(long long i=1;i<=m;i++){
76         long long a;
77         scanf("%lld",&a);
78         belong[a].push_back(i); 
79     }
80     for(long long i=1;i<=n;i++){
81         scanf("%lld",&target[i]);
82         con[i]=i;
83     }
84     scanf("%lld",&k);
85     for(long long i=1;i<=k;i++){
86         scanf("%lld%lld%lld",&ls[i],&rs[i],&val[i]);
87     }
88     k++;
89     ls[k]=1;rs[k]=m;val[k]=INF;
90     now=0;
91     query(1,k,1,n);
92     for(long long i=1;i<=n;i++){
93         if(ans[i]==k)printf("NIE\n");
94         else printf("%lld\n",ans[i]);
95     }
96     return 0;
97 } 
View Code

 

posted @ 2018-08-04 09:25  Xu-daxia  阅读(122)  评论(0编辑  收藏  举报