• 胡扯两句——CDQ分治


    之前听大神讲过CDQ分治大概是个什么东西,但是一直还没有真正去搞过。今天稍微看了一下,写点自己的理解。

    首先CDQ分治有两个条件。

    条件1:可以分成两个独立互不影响的问题(这里的“独立”是指将前面区间的影响处理掉后,后面与前面都成为了新的相同问题)

    条件2:允许离线(据说最近流行强制在线。。。如果这样只好去写恶心的数据结构了)。

    CDQ分治在可以使用的情况下很多高级数据结构题可以用CDQ分治干过去,不仅时空优越而且易于调试(虽然我并不觉得很好调试

    大体思路是将问题不断分成两个子问题,用前一个子问题中的修改操作去更新后一个子问题,这样之后就得到了两个互不影响的子问题,达到分治的目的。

    贴一道版题代码:BZOJ 1176

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define lowbit(x) ((x)&-(x))
     4 struct data{
     5        int v,x,y,d,f,pos;
     6        bool operator <(const data& w)const{
     7        if(x!=w.x) return x<w.x;
     8        if(y!=w.y) return y<w.y;
     9        return pos<w.pos;
    10     }
    11 }a[200005],tmp[200005];
    12 int s,w,t[2000005],cnt,ans[200005];
    13 int read(int& x){
    14     x=0; int f=1,a=getchar();
    15     while(a<'0' || a>'9') {if(a=='-') f=-1; a=getchar();}
    16     while(a>='0' && a<='9') x=x*10+a-'0',a=getchar(); x*=f;
    17 }
    18 inline void add(int y,int x){for(int i=y;i<=w;i+=lowbit(i)) t[i]+=x;}
    19 inline int query(int y){int ret=0; for(int i=y;i;i-=lowbit(i)) ret+=t[i]; return ret;}
    20 void CDQ(int l,int r){
    21     if(l==r) return;
    22     int mid=(l+r)>>1,t1=l-1,t2=mid; //这里写错调了老半天
    23     for(int i=l;i<=r;i++){
    24         if(a[i].v<=mid && !a[i].pos) add(a[i].y,a[i].d);
    25         if(a[i].v>mid && a[i].pos) ans[a[i].pos]+=query(a[i].y)*a[i].f;
    26     }
    27     for(int i=l;i<=r;i++)
    28         if(a[i].v<=mid && !a[i].pos) add(a[i].y,-a[i].d);
    29     for(int i=l;i<=r;i++)
    30         if(a[i].v<=mid) tmp[++t1]=a[i];
    31         else tmp[++t2]=a[i];
    32     for(int i=l;i<=r;i++) a[i]=tmp[i];
    33     CDQ(l,mid); CDQ(mid+1,r);
    34 }
    35 int main(){
    36     read(s); read(w); int t,x,y,d,x1,x2,y1,y2;
    37     while(1){
    38         read(t);
    39         if(t==1){
    40             read(x); read(y); read(d);
    41             a[++cnt]=(data){cnt,x,y,d,1,0};
    42         }else if(t==2){
    43             read(x1); read(y1); read(x2); read(y2); ++ans[0];
    44             a[++cnt]=(data){cnt,x1-1,y1-1,0,1,ans[0]};
    45             a[++cnt]=(data){cnt,x2,y2,0,1,ans[0]};
    46             a[++cnt]=(data){cnt,x1-1,y2,0,-1,ans[0]};
    47             a[++cnt]=(data){cnt,x2,y1-1,0,-1,ans[0]};
    48         }else break;
    49     }
    50     sort(a+1,a+1+cnt);
    51     CDQ(1,cnt);
    52     for(int i=1;i<=ans[0];i++)
    53     printf("%d
    ",ans[i]);
    54     return 0;
    55 }
  • 相关阅读:
    Leetcode 回溯法 典型例题
    LeetCode 回溯法 别人的小结 八皇后 递归
    回溯算法 LEETCODE别人的小结 一八皇后问题
    python学习 面向对象高级编程
    python 学习 面向对象编程
    python 学习 模块
    python 学习 map /reduce
    pyhton 学习 函数式编程
    python学习 函数
    使用dict和set
  • 原文地址:https://www.cnblogs.com/enigma-aw/p/5980848.html
Copyright © 2020-2023  润新知