P3527 [POI2011] MET-Meteors entire bipartite

  All the points after a given point of a ring, each node has a home country, k incident, every time [l, r] every little bit right on the interval plus a value for each of the first countries seeking how many operations right and can reach a value

 

Very good overall template-half title

Before modification and inquiry are all thrown together inside the structure of divide and conquer this problem without such (because the inquiry is the first modification of) so only to be asked to partition can reduce the amount of code a lot (but before the template title not suitable for this dichotomy is before traversing range if the range is too high, then the complexity of this problem is not a natural-half of the value domain but the number of operations!)

 

Note that a ring is given when the left end of the processing interval is greater than the right end of the right end point plus the length of the interval (i.e. expanded into a chain) while the array in the tree when asked to add two values ​​(a value another big than m)

 

+1 half of the time when not satisfy the right boundary to jump right boundary +1

#include<bits/stdc++.h>
using namespace std;
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define repp(i,a,b) for(int i=(a);i>=(b);--i)
#define ll long long
#define see(x) (cerr<<(#x)<<'='<<(x)<<endl)
#define inf 0x3f3f3f3f
#define CLR(A,v)  memset(A,v,sizeof A)
//////////////////////////////////
const int N=2e6+10;
int n,m,ans[N],zuo[N],you[N],pos,head[N],k,x;
ll v[N],t[N];
struct Edge{int to,nex;}edge[N<<1];
void add(int a,int b){edge[++pos]=(Edge){b,head[a]};head[a]=pos;}
void upnode(int x,int v){for(;x<=N;x+=x&-x)t[x]+=v;}
ll qsum(int x){ll ans=0;for(;x;x-=x&-x)ans+=t[x];return ans;}
struct node{ll id,need;}s[N],temp1[N],temp2[N];

void solve(int L,int R,int l,int r)
{
    if(l>r)return ;
    if(L==R){rep(i,l,r)ans[s[i].id]=L;return ;}
    int mid=(L+R)>>1;
    rep(i,L,mid)upnode(zuo[i],v[i]),upnode(you[i]+1,-v[i]);
    int cnt1=0,cnt2=0;
    rep(i,l,r)
    {    
        ll sum=0;
        for(int j=head[s[i].id];j&&sum<=s[i].need;j=edge[j].nex)
        sum+=qsum(edge[j].to)+qsum(edge[j].to+m);
        if(sum>=s[i].need)temp1[++cnt1]=s[i];
        else temp2[++cnt2]=s[i],temp2[cnt2].need-=sum;
    }
    rep(i,L,mid)upnode(zuo[i],-v[i]),upnode(you[i]+1,v[i]);//谁污染谁治理
    
    rep(i,1,cnt1)s[l-1+i]=temp1[i];
    rep(i,1,cnt2)s[l+cnt1-1+i]=temp2[i];
    solve(L,mid,  l,l+cnt1-1);solve(mid+1,R,l+cnt1,r);
}
int main()
{
    scanf("%d%d",&n,&m);
    rep(i,1,m)scanf("%d",&x),add(x,i);
    rep(i,1,n)scanf("%lld",&s[i].need),s[i].id=i;
    scanf("%d",&k);
    rep(i,1,k){scanf("%d%d%lld",&zuo[i],&you[i],&v[i]);if(you[i]<zuo[i])you[i]+=m;}
    solve(1,k+1,1,n);
    rep(i,1,n)
    if(ans[i]==k+1)printf("NIE\n");
    else printf("%d\n",ans[i]);
    return 0;
}
View Code

 

Guess you like

Origin www.cnblogs.com/bxd123/p/11547889.html