zoukankan      html  css  js  c++  java
  • CDQ分治入门

    用CDQ分治实现了一下树状数组的功能,初步了解了CDQ分治的基本流程。

    常数大概是树状数组的一倍吧。。

    CDQ分治: 左区间只处理修改,右区间只处理询问。 即,考虑左区间的修改对右区间的询问产生的影响。

    #include<bits/stdc++.h>
    using namespace std;
    const int N=500010;
    struct Node{
        int type,pos,v;//type=1表示修改,type=2表示查询左端点,type=3表示查询右端的
        bool operator<(const Node& k)const{return pos==k.pos?type<k.type:pos<k.pos;}
    }que[N*3];
    int n,m,totq,ans[N],tota;
    Node temp[N*3];
    void cdq(int l,int r){
        if(r<=l) return;
        int mid=(l+r)>>1;
        cdq(l,mid);cdq(mid+1,r);
        int ii=l,jj=mid+1,x=l,sum=0;
        while(ii<=mid&&jj<=r){
            if(que[ii]<que[jj]){
                if(que[ii].type==1) sum+=que[ii].v; 
                temp[x++]=que[ii++];
            }else{
                if(que[jj].type!=1) ans[que[jj].v]+=(que[jj].type==3?1:-1)*sum;
                temp[x++]=que[jj++];
            }
        }
        while(ii<=mid) temp[x++]=que[ii++];
        while(jj<=r){
            if(que[jj].type!=1){
                ans[que[jj].v]+=(que[jj].type==3?1:-1)*sum;
            }
            temp[x++]=que[jj++];
        }
        for(int i=l;i<=r;i++) que[i]=temp[i];
        return; 
    }
    int main(){
        int t1,t2,opt;
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++) scanf("%d",&t1),que[++totq]=(Node){1,i,t1};
        for(int i=1;i<=m;i++){
            scanf("%d%d%d",&opt,&t1,&t2);
            if(opt==1){
                que[++totq]=(Node){1,t1,t2};
            }else{
                tota++;
                que[++totq]=(Node){2,t1-1,tota};
                que[++totq]=(Node){3,t2,tota};
            }
        }
        cdq(1,totq);
        for(int i=1;i<=tota;i++) printf("%d
    ",ans[i]);
        return 0;
    }
  • 相关阅读:
    CentOS7配置本地yum源和在线yum源
    Centos7中安装samba服务器
    phpmydmain登录问题
    java实现简单的加法器
    我的偶像 凯文 米特尼克 简介
    安全好的地方分享
    a标签
    Vmware虚拟机 的工作模式
    java面板
    java的套接字实现远程连接
  • 原文地址:https://www.cnblogs.com/mycups/p/8528058.html
Copyright © 2011-2022 走看看