zoukankan      html  css  js  c++  java
  • BZOJ 2527: [Poi2011]Meteors [整体二分]

    传送门

    题意:

    一个星球环形带上分为 $M$ 个区域,$n$个国家,$k$天,每个区域可能有若干国家的陨石收集器,每一天有一段连续区域下陨石雨,
    其上所有收集器都为本国家收集到 $D_i$ 的陨石,每个国家有一定的陨石需求量$P_i$,求每个国家第几天收集陨石量恰好满足需求
    $1 le n,m,k le 3∗10^5quad  1 le A_i,P_i < 10^9$


    整体二分

    $zyz:$整体二分是在权值上进行$CDQ$分治

    我觉得更像是说$:$整体二分是在答案上进行$CDQ$分治

    整体二分是二分答案在数据结构题上的扩展

    因为数据结构题二分的答案通常是第几个操作之后,需要进行哪些操作之后才能判断

    核心就是维护一个$cur$数组保存当前的影响

    $Sol(l,r,S) l,r$是当前

    操作$[l,mid]$的影响(对答案的贡献),加上$cur$看看与询问相比大小分成左右递归分治

    询问集合保存编号就好了

    是不是命名有点奇怪,q是操作,a是询问。。。所以说无视这份代码吧

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    #define lc x<<1
    #define rc x<<1|1
    #define lson x<<1,l,mid
    #define rson x<<1|1,mid+1,r
    const int N=3e5+5,INF=1e9;
    typedef long long ll;
    inline int read(){
        char c=getchar();int x=0,f=1;
        while(c<'0'||c>'9'){if(c=='-')f=-1; c=getchar();}
        while(c>='0'&&c<='9'){x=x*10+c-'0'; c=getchar();}
        return x*f;
    }
    int n,m,k;
    struct edge{
        int v,ne;
    }e[N];
    int h[N],cnt;
    inline void ins(int u,int v){
        cnt++;
        e[cnt].v=v;e[cnt].ne=h[u];h[u]=cnt;
    }
    int a[N],t1[N],t2[N],lim[N];
    struct Meteor{
        int l,r,w;
    }q[N];
    ll c[N];
    inline int lowbit(int x){return x&-x;}
    inline void _add(int p,ll v){for(;p<=m;p+=lowbit(p)) c[p]+=v;}
    inline ll sum(int p){
        ll re=0;
        for(;p;p-=lowbit(p)) re+=c[p];
        return re;
    }
    inline void add(int l,int r,int v){
        _add(l,v);_add(r+1,-v);
    }
    ll cur[N];
    int ans[N];
    void Sol(int l,int r,int sl,int sr){//printf("Sol %d %d %d %d
    ",l,r,sl,sr);
        if(sl>sr) return;
        if(l==r){
            for(int i=sl;i<=sr;i++) ans[a[i]]=l;
            return;
        }
        int mid=(l+r)>>1;
        for(int i=l;i<=mid;i++){
            if(q[i].l<=q[i].r) add(q[i].l,q[i].r,q[i].w);
            else add(1,q[i].r,q[i].w),add(q[i].l,m,q[i].w);
        }
        int p1=0,p2=0;
        for(int i=sl;i<=sr;i++){
            int u=a[i];ll s=cur[u],p=lim[u];
            for(int k=h[u];k;k=e[k].ne)
                if((s+=sum(e[k].v))>=p) break;
            if(s>=p) t1[++p1]=u;
            else t2[++p2]=u,cur[u]=s;
        }
        for(int i=l;i<=mid;i++){
            if(q[i].l<=q[i].r) add(q[i].l,q[i].r,-q[i].w);
            else add(1,q[i].r,-q[i].w),add(q[i].l,m,-q[i].w);
        }
        for(int i=1;i<=p1;i++) a[sl+i-1]=t1[i];
        for(int i=1;i<=p2;i++) a[sl+p1+i-1]=t2[i];
        Sol(l,mid,sl,sl+p1-1);
        Sol(mid+1,r,sl+p1,sr);
    }
    int main(){
        freopen("in","r",stdin);
        n=read();m=read();
        for(int i=1;i<=m;i++) ins(read(),i);
        for(int i=1;i<=n;i++) lim[i]=read(),a[i]=i;
        k=read();
        for(int i=1;i<=k;i++) q[i].l=read(),q[i].r=read(),q[i].w=read();
        q[++k].l=1;q[k].r=m;q[k].w=INF;
        Sol(1,k,1,n);
        //for(int i=1;i<=n;i++) printf("%d %d %lld
    ",i,ans[i],cur[i]);
        for(int i=1;i<=n;i++){
            if(ans[i]!=k) printf("%d
    ",ans[i]);
            else puts("NIE");
        }
    }
  • 相关阅读:
    python的元类
    中国的互联网:草根与精英
    PEP8中文翻译
    一些重要的算法
    tornado模板语法
    C#l类与对象
    sql_ 存储过程
    SQL_触发器
    SQL_事务处理
    C#_方法
  • 原文地址:https://www.cnblogs.com/candy99/p/6443835.html
Copyright © 2011-2022 走看看