zoukankan      html  css  js  c++  java
  • CDQ 分治算法模板

    CDQ分治

    1.三维偏序问题:三维偏序(陌上花开)

    #include<bits/stdc++.h>
    #define RG register
    #define IL inline
    #define _ 200005
    using namespace std;
    IL int gi(){
        RG int data = 0 , m = 1; RG char ch = 0;
        while(ch != '-' && (ch<'0'||ch>'9'))ch = getchar();
        if(ch == '-'){m = -1; ch = getchar();}
        while('0'<=ch && ch<='9')
            data = (data<<3) + (data<<1) + (ch - '0') , ch = getchar();
        return (m) ? data : -data;
    }
    
    int tot,bt[_],n,k,f[_],g[_],blg[_]; long long ans[_];
    
    struct Node{
        int a, b, c , w , id;
        //w记录这个节点对应多少个真实节点,id则是其对应编号.
        bool operator <(const Node &B)const{
             return (b == B.b) ? c <= B.c : b < B.b;}
    };
    Node q1[_],q[_],tmp[_];
    
    namespace BIT{
        IL void Update(RG int ps,RG int dt){
           for(RG int i = ps; i <= k; i += (i&-i))bt[i] += dt;
        }
        IL void Clear(RG int ps){
           for(RG int i = ps; i <= k; i += (i&-i))bt[i] = 0;
        }
        IL int Query(RG int ps){
            RG int res = 0;
            for(RG int i = ps; i > 0; i -= (i&-i))res += bt[i];
            return res;
        }
    }
    
    void cdq(RG int L,RG int R){
        if(L == R)return;
        RG int mid = (L+R)>>1; cdq(L,mid); cdq(mid+1,R);
        RG int l = L , r = mid+1 , oo = L-1;
        while(l <= mid && r <= R){
            if(q[l] < q[r])
                BIT::Update(q[l].c,q[l].w) ,
                tmp[++oo] = q[l++];
            else
                g[q[r].id] += BIT::Query(q[r].c) ,
                tmp[++oo] = q[r++];
        }
        while(l <= mid)tmp[++oo] = q[l++];
        while(r <= R)
            g[q[r].id] += BIT::Query(q[r].c) ,
            tmp[++oo] = q[r++];
        for(RG int i = L; i <= R; i ++)
            BIT::Clear(tmp[i].c) , q[i] = tmp[i];
        return;
    }
    
    IL bool cmp(Node a,Node b){
        if(a.a != b.a)return a.a < b.a;
        if(a.b != b.b)return a.b < b.b;
        if(a.c != b.c)return a.c < b.c;
        return a.id < b.id;   //注意:这里一定要随便定义一个优先级
    }
    IL bool Equl(int nw,int cp){
        if(!cp)return false;
        else  return (q1[nw].a==q[cp].a &&
              q1[nw].b==q[cp].b && q1[nw].c==q[cp].c);
    }
    
    int main(){
        n = gi(); k = gi();
        for(RG int i = 1,a,b,c; i <= n; i ++)
            a = gi(),b = gi(),c = gi(),
            q1[i] = (Node){a , b , c , 1 , i};
        
        //去重:
        tot = 0;
        sort(q1+1,q1+n+1,cmp);
        for(RG int i = 1; i <= n; i ++){
            if(!Equl(i,tot))
                q[++tot] = q1[i] , q[tot].w = 1 , q[tot].id = tot;
            else q[tot].w ++;
            blg[i] = tot;          //记录i点是对应去重后的哪个节点
        }
    
        cdq(1,tot);
        // f[i] 表示去重前点i满足 (aj<=ai,bj<=bi,cj<=ci) 的j的个数.
        // g[i] 表示去重后点i满足条件的j的个数
        for(RG int i = 1; i <= tot; i ++)g[q[i].id] += q[i].w-1;
        for(RG int i = 1; i <= n; i ++)f[i] = g[blg[i]];
        for(RG int i = 1; i <= n; i ++)ans[f[i]] ++;
        for(RG int i = 0; i < n; i ++)printf("%lld\n",ans[i]);
        return 0;
    }
    

    2.动态逆序对问题:[CQOI2011]动态逆序对

    #include<bits/stdc++.h>
    #define RG register
    #define IL inline
    #define _ 300005
    using namespace std;
    
    IL int gi(){
        RG int data = 0 , m = 1; RG char ch = 0;
        while(ch != '-' && (ch<'0'||ch>'9'))ch = getchar();
        if(ch == '-'){m = -1; ch = getchar();}
        while('0'<=ch && ch<='9')
            data = (data<<3) + (data<<1) + (ch - '0') , ch = getchar();
        return (m) ? data : -data;
    }
    
    struct Query{
      int tm , ps , val;
      bool operator < (const Query &B)const{ return ps < B.ps; }
    };
    Query q[_] , tmp[_];
    int ans[_],bt[_],n,m,pos[_]; long long Ans; bool vis[_];
    
    namespace BIT{
        IL void Update(RG int ps,RG int dt){
           for(RG int i = ps; i <= n; i += (i&-i))bt[i] += dt;
        }
        IL int Query(RG int ps){
            RG int res = 0;
            for(RG int i = ps; i > 0; i -= (i&-i))res += bt[i];
            return res;
        }
    }
    
    void cdq(RG int L,RG int R){
        if(L == R)return;
      	RG int mid = (L+R)>>1; cdq(L,mid);  cdq(mid+1,R);
      	RG int l = L , r = mid+1 , oo = L-1;
        while(l<=mid && r<=R)
     	    if(q[l] < q[r])tmp[++oo] = q[l++];  else tmp[++oo] = q[r++];
        while(l<=mid)tmp[++oo] = q[l++];
        while(r<=R)tmp[++oo] = q[r++];
        for(RG int i = L; i <= R; i ++)q[i] = tmp[i];
    
        //get - behind - smaller
      	for(RG int i = L; i <= R; i ++)
            if(q[i].tm <= mid)BIT::Update(q[i].val,1);
            else ans[q[i].tm] += BIT::Query(n) - BIT::Query(q[i].val);         
      	for(RG int i = L; i <= R; i ++)
            if(q[i].tm <= mid)BIT::Update(q[i].val,-1);
    
        //get - front - bigger
      	for(RG int i = R; i >= L; i --)
            if(q[i].tm <= mid)BIT::Update(q[i].val,1);
            else ans[q[i].tm] += BIT::Query(q[i].val);
        for(RG int i = R; i >= L; i --)
            if(q[i].tm <= mid)BIT::Update(q[i].val,-1);
    
        return;
    }
    
    IL bool cmp(Query a,Query b){return a.tm<b.tm;}
    
    int main(){
        n = gi(); m = gi();
        RG int tot = 0;
        for(RG int u,i = 1; i <= n; i ++)
            u = gi() , pos[u] = i , vis[u] = 1;
        for(RG int u,i = n; i >= n-m+1; i --)
            u = gi() , vis[u] = 0 ,
            q[++tot] = (Query){i,pos[u],u};
        RG int cnt = n - m + 1;
        for(RG int i = 1; i <= n; i ++)
            if(vis[i])q[++tot] = (Query){--cnt,pos[i],i};
        sort(q+1,q+tot+1,cmp);
        cdq(1,tot);
        Ans = 0;
        for(RG int i = 1; i <= n; i ++)Ans += ans[i];
        for(RG int i = n; i >= n-m+1; i --)
            printf("%lld\n",Ans) , Ans -= ans[i];
        return 0;
    }
    

    离线修改与查询问题:树状数组 1

    #include<bits/stdc++.h>
    #define RG register
    #define IL inline
    #define ll long long
    #define _ 4*500005
    using namespace std;
    
    int n,m,ask,tot; ll ans[_];
    
    struct Do{
        int typ,pos,val;
        bool operator <(const Do &B)const{
        return (pos == B.pos)?typ < B.typ : pos < B.pos; }
    };
    Do q[_],tmp[_];
    
    void cdq(RG int L,RG int R){
        if(L == R)return;
        RG int mid = (L+R)>>1; cdq(L,mid); cdq(mid+1,R);
        RG ll upt = 0 , l = L , r = mid+1 , oo = 0;
        while(l <= mid && r <= R){
            if(q[l] < q[r]){
                if(q[l].typ == 1)upt += q[l].val;
                tmp[++oo] = q[l++];
            }
            else {
                if(q[r].typ == 2)ans[q[r].val] -= upt;
                if(q[r].typ == 3)ans[q[r].val] += upt;
                tmp[++oo] = q[r++];
            }
        }
        while(l <= mid){
            if(q[l].typ == 1)upt += q[l].val;
            tmp[++oo] = q[l++];
        }
        while(r <= R){
            if(q[r].typ == 2)ans[q[r].val] -= upt;
            if(q[r].typ == 3)ans[q[r].val] += upt;
            tmp[++oo] = q[r++];
        }
        for(RG int i = L; i <= R; i ++)q[i] = tmp[i-L+1];
    }
    
    int main(){
        scanf("%d %d",&n,&m);
        for(RG int i = 1,ww; i <= n; i ++)
            scanf("%d",&ww), q[++tot] = (Do){1,i,ww};
        ask = 0;
        for(RG int i = 1,tp,ps,ww; i <= m; i ++){
            scanf("%d %d %d",&tp,&ps,&ww);
            if(tp == 1)q[++tot] = (Do){1,ps,ww};
            else
                q[++tot] = (Do){2,ps-1,++ask} ,
                q[++tot] = (Do){3,ww,ask};
        }
        cdq(1,tot);
        for(RG int i = 1; i <= ask; i ++)cout<<ans[i]<<endl;
        return 0;
    }
    
    

  • 相关阅读:
    集成TBS(腾讯浏览服务)x5内核的webView
    android studio 华为手机看不到具体的错误日志
    android混淆那些事
    通用工具
    用队列来处理订单以及集合间性能比较
    从.Net版本演变看String和StringBuilder性能之争
    从事件来看委托
    从矢量来看运算符重载
    从foreach语句枚举元素看数组
    从装箱拆箱看泛型
  • 原文地址:https://www.cnblogs.com/Guess2/p/8367160.html
Copyright © 2011-2022 走看看