zoukankan      html  css  js  c++  java
  • 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
    ",ans[i]);
        }
        return 0;
    }
    #undef ST
  • 相关阅读:
    总结Android逆向入门成长必备技能
    BootKit病毒——“异鬼Ⅱ”的前世今生
    NSA武器库知识整理
    SQL菜鸟学习札记(二)
    SQL菜鸟学习札记(一)
    梦织未来Windows驱动编程 第06课 驱动对磁盘文件的操作
    梦织未来Windows驱动编程 第05课 小结(读取另一驱动,遍历所有驱动)
    梦织未来Windows驱动编程 第03课 驱动的编程规范
    【原创】信息搜索力
    【原创】经典排序回顾
  • 原文地址:https://www.cnblogs.com/ihopenot/p/6164321.html
Copyright © 2011-2022 走看看