Bzoj2527--Poi2011Meteor

整体二分的题

以前没有写过整体二分的题,感受了一下

大概是把答案和所有的询问一同二分,就是把满足当前二分区间的询问和不满足的分开后递归下去

复杂度由主定理保证,里面的复杂度必须是之和二分后的区间线性相关,而不是与整个区间相关,复杂度才有保证

有点cdq的感觉

代码 :

#include<bits/stdc++.h>
#define LL long long
using namespace std;

#define INF 1000000000
#define MAXN 300005

int n,m,t,id[MAXN],Ml[MAXN],Mr[MAXN],A[MAXN],mis[MAXN];
int head[MAXN],to[MAXN*2];
int ans[MAXN];

namespace SegmentTree{
    
    const int L=0,R=1;
    struct node{
        int son[2];LL add;
    }x[MAXN*2];
    int sz=1;
    
    void _init(int l,int r,int num) {
        if(l==r) return;
        int mid=l+r>>1;
        x[num].son[L]=++sz;x[num].son[R]=++sz;
        _init(l,mid,x[num].son[L]);
        _init(mid+1,r,x[num].son[R]);
    }
    
    void Add(int l,int r,int nl,int nr,int num,int v) {
        if(l==nl&&r==nr) {x[num].add+=v;return;}
        int mid=nl+nr>>1;
        if(l>mid) Add(l,r,mid+1,nr,x[num].son[R],v);
        else if(r<=mid) Add(l,r,nl,mid,x[num].son[L],v);
        else {
            Add(l,mid,nl,mid,x[num].son[L],v);
            Add(mid+1,r,mid+1,nr,x[num].son[R],v);
        }
    }
    
    LL Qurey(int pos,int l,int r,int num) {
        if(l==r) return x[num].add;
        int mid=l+r>>1;
        if(pos<=mid) return Qurey(pos,l,mid,x[num].son[L])+x[num].add;
        else return Qurey(pos,mid+1,r,x[num].son[R])+x[num].add;
    }
}
#define ST SegmentTree

bool f[MAXN];
void solve(int l,int r,int L,int R) {
    if(l>r) return;
    if(L==R) {
        for(int i=l;i<=r;i++) ans[id[i]]=L;
        return;
    }
    int mid=L+R>>1;
    for(int i=L;i<=mid;i++) {
        if(Ml[i]<=Mr[i]) ST::Add(Ml[i],Mr[i],1,m,1,A[i]);
        else {
            ST::Add(Ml[i],m,1,m,1,A[i]);
            ST::Add(1,Mr[i],1,m,1,A[i]);
        }
    }
    for(int i=l;i<=r;i++) {
        LL get=0;
        for(int j=head[id[i]];j;j=to[j]) {
            get+=ST::Qurey(j,1,m,1);
            if(get>=mis[id[i]]) break;
        }
        if(get<mis[id[i]]) f[id[i]]=1,mis[id[i]]-=get;
    }
    int p1=l,p2=r;
    while(p2>p1) {
        while(p2>p1&&!f[id[p1]]) p1++;
        while(p2>p1&&f[id[p2]]) p2--;
        if(p2>p1) swap(id[p1],id[p2]);
    }
    p1=l-1;
    for(int i=l;i<=r;i++) {if(!f[id[i]]) p1=i;f[id[i]]=0;}
    for(int i=L;i<=mid;i++) {
        if(Ml[i]<=Mr[i])    ST::Add(Ml[i],Mr[i],1,m,1,-A[i]);
        else {
            ST::Add(Ml[i],m,1,m,1,-A[i]);
            ST::Add(1,Mr[i],1,m,1,-A[i]);
        }
    }
    solve(l,p1,L,mid);solve(p1+1,r,mid+1,R);
}

int main() {
    scanf("%d%d",&n,&m);
    for(int a,i=1;i<=m;i++) {
        scanf("%d",&a);
        to[i]=head[a];head[a]=i;
    }
    for(int i=1;i<=n;i++) {
        scanf("%d",&mis[i]);id[i]=i;
    }
    scanf("%d",&t);
    for(int i=1;i<=t;i++) {
        scanf("%d%d%d",&Ml[i],&Mr[i],&A[i]);
    }
    A[++t]=INF;Ml[t]=1;Mr[t]=m;
    ST::_init(1,m,1);
    solve(1,n,1,t);
    for(int i=1;i<=n;i++) {
        if(ans[i]==t) puts("NIE");
        else printf("%d\n",ans[i]);
    }
    return 0;
}
#undef ST

 

posted @ 2016-12-12 14:18  ihopenot  阅读(230)  评论(0编辑  收藏  举报