POI2011-Meteors

做这道题本来只是为了作为整体二分的练手题的,结果发现在bzoj上这是权限题,于是我在一个奇怪的oj上找到了这道题.

地址为https://szkopul.edu.pl/problemset/problem/czzVm7v3I58TnPHzBgWiyELT/site/?key=statement

然后我因为我把我的代码中lcnt和rcnt开成了全局变量查了半个多小时...

代码如下..

#include<cstdio>
#include<vector>
using namespace std;
const int N=300010,inf=0x3f3f3f3f;
int n,m,k,p[N],cur[N],tmp[N],ans[N],id[N],c[N],lv[N],rv[N];
vector<int> G[N];
struct data{int l,r,v;}q[N];
void add(int i,int v){for(;i<=m;i+=i&-i) c[i]+=v;}
void add(int l,int r,int v){add(l,v); add(r+1,-v);}
int query(int i){int ans=0; for(;i;i-=i&-i) ans+=c[i]; return ans;}
void solve(int cl,int cr,int ql,int qr){
    if(cl>cr) return;
    if(ql==qr){
        for(int i=cl;i<=cr;++i) ans[id[i]]=ql; return;
    }
    int mid=(ql+qr)/2;
    for(int i=ql;i<=mid;++i){
        if(q[i].l<=q[i].r) add(q[i].l,q[i].r,q[i].v);
        else add(q[i].l,m,q[i].v),add(1,q[i].r,q[i].v);
    }
    int lcnt=0,rcnt=0;
    for(int i=cl;i<=cr;++i){
        tmp[id[i]]=0;
        for(int j=0;j<G[id[i]].size();++j){
            tmp[id[i]]+=query(G[id[i]][j]);
            if(tmp[id[i]]+cur[id[i]]>p[id[i]]) break;
        }
        if(tmp[id[i]]+cur[id[i]]>=p[id[i]]) lv[++lcnt]=id[i];
        else cur[id[i]]+=tmp[id[i]],rv[++rcnt]=id[i];
    }
    for(int i=ql;i<=mid;++i){
        if(q[i].l<=q[i].r) add(q[i].l,q[i].r,-q[i].v);
        else add(q[i].l,m,-q[i].v),add(1,q[i].r,-q[i].v);
    }
    for(int i=1;i<=lcnt;++i) id[cl+i-1]=lv[i];
    for(int i=1;i<=rcnt;++i) id[cl+lcnt+i-1]=rv[i];
    solve(cl,cl+lcnt-1,ql,mid); solve(cl+lcnt,cr,mid+1,qr);
}
int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;++i){
        int x; scanf("%d",&x); G[x].push_back(i);
    }
    for(int i=1;i<=n;++i) scanf("%d",&p[i]),id[i]=i;
    scanf("%d",&k);
    for(int i=1;i<=k;++i) scanf("%d%d%d",&q[i].l,&q[i].r,&q[i].v);
    q[++k].l=1; q[k].r=m; q[k].v=inf;
    solve(1,n,1,k); for(int i=1;i<=n;++i) if(ans[i]==k) printf("NIE\n");
    else printf("%d\n",ans[i]); return 0;
}

 

posted @ 2017-09-08 20:26  jxcakak  阅读(169)  评论(0编辑  收藏  举报