• COGS 2479. [HZOI 2016] 偏序 (CDQ套CDQ)


    传送门

    解题思路

    四维偏序问题,模仿三维偏序,第一维排序,第二维CDQ,最后剩下二元组,发现没办法处理,就继续嵌套CDQ分治。首先把二元组的左右两边分别打上不同的标记,因为统计答案时只统计左边对右边的影响,然后再进行一个CDQ解决第三维,最后用树状数组解决最后一维。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    
    using namespace std;
    const int MAXN = 50005;
    const int LEFT = 1;
    const int RIGHT = 2;
    typedef long long LL;
    
    inline int rd(){
        int x=0,f=1;char ch=getchar();
        while(!isdigit(ch)) {f=ch=='-'?0:1;ch=getchar();}
        while(isdigit(ch))  {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
        return f?x:-x;
    }
    
    int n;
    LL ans,f[MAXN];
    
    struct Query{
        int a,b,c,id,New;
    }q[MAXN],tmp[MAXN],tmp_[MAXN];
    
    void update(int x,int k){
        for(;x<=n;x+=x&-x) f[x]+=k;
    }
    
    LL query(int x){
        LL ret=0;
        for(;x;x-=x&-x) ret+=f[x];
        return ret;
    }
    
    void Clear(int x){
        for(;x<=n;x+=x&-x) f[x]=0;
    }
    
    void CDQ(int l,int r){
        if(l==r) return;
        int mid=l+r>>1;CDQ(l,mid);CDQ(mid+1,r);
        int L=l,R=mid+1,o=l;
        while(L<=mid && R<=r){
            if(tmp[L].b<tmp[R].b){
                if(tmp[L].New==LEFT) update(tmp[L].c,1);
                tmp_[o++]=tmp[L++];
            }
            else{
                if(tmp[R].New==RIGHT) ans+=query(tmp[R].c);
                tmp_[o++]=tmp[R++];
            }
        }
        while(L<=mid) tmp_[o++]=tmp[L++];
        while(R<=r) {
            if(tmp[R].New==RIGHT) ans+=query(tmp[R].c);
            tmp_[o++]=tmp[R++];
        }
    //    memset(f,0,sizeof(f));
        for(register int i=l;i<=mid;i++) if(tmp[i].New==LEFT) Clear(tmp[i].c);
        for(register int i=l;i<=r;i++) tmp[i]=tmp_[i];
    }
    
    void cdq(int l,int r){
        if(l==r) return;
        int mid=l+r>>1;cdq(l,mid);cdq(mid+1,r);
        int L=l,R=mid+1,o=l;
        while(L<=mid && R<=r){
            if(q[L].a<q[R].a) {
                q[L].New=LEFT;
                tmp[o++]=q[L++];
            }
            else {
                q[R].New=RIGHT;
                tmp[o++]=q[R++];
            }
        }
        while(L<=mid) {q[L].New=LEFT;tmp[o++]=q[L++];}
        while(R<=r)  {q[R].New=RIGHT;tmp[o++]=q[R++];}
        for(register int i=l;i<=r;i++) q[i]=tmp[i];
        CDQ(l,r);
    }
    
    int main(){
    //    freopen("data.txt","r",stdin);
    //    freopen("wrong.txt","w",stdout);
        freopen("partial_order.in","r",stdin);
        freopen("partial_order.out","w",stdout);
        n=rd();
        for(int i=1;i<=n;i++) q[i].a=rd(),q[i].id=i;
        for(int i=1;i<=n;i++) q[i].b=rd();
        for(int i=1;i<=n;i++) q[i].c=rd();
        cdq(1,n);cout<<ans<<endl;
        return 0;
    }
    View Code
  • 相关阅读:
    20135313_exp4
    20135313_exp5
    学习分块
    学习BM算法
    学习笛卡尔树
    【数学】Eddy Walker
    【bitset】Kth Minimum Clique
    【搜索】n的约数
    【搜索】Partition problem
    【信息学奥赛一本通 提高组】第四章 广搜的优化技巧
  • 原文地址:https://www.cnblogs.com/sdfzsyq/p/9700580.html
Copyright © 2020-2023  润新知