CDQ分治练习

 

cdq分治解决偏序整体二分解决区间k小思路相似,都是考虑左区间对右区间的影响,但是实现略有不同

偏序的重点是:理解两个有序链表的合并,即,一次归并排序

整体二分的重点是:二分权值,把操作(查询与修改)划分到左右区间,然后递归处理

 

 

陌上花开

x排序,y分治,z树状数组

/*author:revolIA*/
#include
using namespace std;
typedef long long ll;
const int maxn = 2e5+7;
int Tree[maxn],n,k;
int out[maxn];
void Add(int x,int val){
    for(;x<=k;x+=x&-x)Tree[x] += val;
}
int query(int x,int ans = 0){
    for(;x;x-=x&-x)ans += Tree[x];
    return ans;
}
struct node{
    int x,y,z;
    int ans,w;
    bool operator < (const node &T)const{
        if(x != T.x)return x>1;
    CDQ(l,mid),CDQ(mid+1,r);
    int L = l,R = mid+1,cnt = l;
    while(L<=mid && R<=r){
        if(Qt[L].y<=Qt[R].y){
            Add(Qt[L].z,Qt[L].w);
            Tmp[cnt++] = Qt[L++];
        }else{
            Qt[R].ans += query(Qt[R].z);
            Tmp[cnt++] = Qt[R++];
        }
    }
    while(R<=r){
        Qt[R].ans += query(Qt[R].z);
        Tmp[cnt++] = Qt[R++];
    }
    for(int i=l;i

 

cogs577.蝗灾

统计矩阵内点数(可带权)

 

/*author:revolIA*/
#include
using namespace std;
typedef long long ll;
const int maxn = 1e6+7;
int Tree[maxn],ans[maxn],w,n,cnt,tot;
void add(int x,int val){while(x<=w)Tree[x] += val,x+=x&-x;}
int query(int x,int ans = 0){while(x)ans += Tree[x],x-=x&-x;return ans;}
struct node{
    int x,y,w;
    int pos,opt;
}Qt[maxn],Tmp[maxn];
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,cnt = l;
    while(L<=mid && R<=r){
        if(Qt[L].x <= Qt[R].x){
            if(!Qt[L].opt)add(Qt[L].y,Qt[L].w);
            Tmp[cnt++] = Qt[L++];
        }else{
            if(Qt[R].opt == 1)ans[Qt[R].pos] -= query(Qt[R].w)-query(Qt[R].y-1);
            if(Qt[R].opt == 2)ans[Qt[R].pos] += query(Qt[R].w)-query(Qt[R].y-1);
            Tmp[cnt++] = Qt[R++];
        }
    }
    while(R<=r){
        if(Qt[R].opt == 1)ans[Qt[R].pos] -= query(Qt[R].w)-query(Qt[R].y-1);
        if(Qt[R].opt == 2)ans[Qt[R].pos] += query(Qt[R].w)-query(Qt[R].y-1);
        Tmp[cnt++] = Qt[R++];
    }
    for(int i=l;iz)swap(x,z);
            if(y>opt)swap(y,opt);
            Qt[++cnt] = {x-1,y,opt,tot,1};
            Qt[++cnt] = {z,y,opt,tot,2};
        }
    }
    CDQ(1,cnt);
    for(int i=1;i<=tot;i++)printf("%d\n",ans[i]);
    return 0;
}

 

 

整体二分,静态区间第k小(主席树)

洛谷p3834

 

/*author:revolIA*/
#include
using namespace std;
typedef long long ll;
const int maxn = 4e5+7,inf = 1e9+7;
int Tree[maxn],n,m;
int ans[maxn];
void Add(int x,int val){
    for(;x<=n;x+=x&-x)Tree[x] += val;
}
int query(int x,int ans = 0){
    for(;x;x-=x&-x)ans += Tree[x];
    return ans;
}
struct node{
    int x,y,k;
    int pos,opt;
}Qt[maxn],Tmp[maxn];
void CDQ(int l,int r,int L,int R){
	if(l>r || L>R)return;
    if(l == r){
    	for(int i=L;i<=R;i++)if(Qt[i].opt){
    		ans[Qt[i].pos] = l;
    	}
    	return;
    }
    int mid = (l+r)>>1;
    int cnl = L,cnr = R;
    for(int i=L;i<=R;i++){
    	if(Qt[i].opt){
    		int sum = query(Qt[i].y)-query(Qt[i].x-1);
    		if(sumx?Mr:x;
    }
    for(int i=1,x,y,k;i<=m;i++){
    	scanf("%d%d%d",&x,&y,&k);
    	Qt[i+n] = {x,y,k,i,1};
    }
    CDQ(Ml,Mr,1,n+m);
    for(int i=1;i<=m;i++)printf("%d\n",ans[i]);
    return 0;
}

 

整体二分,动态区间k小(带修主席树)

Zoj2112.Dynamic Rankings

 

/*author:revolIA*/
#include
using namespace std;
typedef long long ll;
const int maxn = 4e5+7,inf = 1e9+7;
int Tree[maxn],n,m,a[maxn];
int ans[maxn],tot,cnt;
void Add(int x,int val){
    for(;x<=n;x+=x&-x)Tree[x] += val;
}
int query(int x,int ans = 0){
    for(;x;x-=x&-x)ans += Tree[x];
    return ans;
}
struct node{
    int x,y,k;
    int pos,opt;
}Qt[maxn],Tmp[maxn];
void CDQ(int l,int r,int L,int R){
	if(l>r || L>R)return;
    if(l == r){
    	for(int i=L;i<=R;i++)if(Qt[i].opt>0){
    		ans[Qt[i].pos] = l;
    	}
    	return;
    }
    int mid = (l+r)>>1;
    int cnl = L,cnr = R;
    for(int i=L;i<=R;i++){
    	if(Qt[i].opt>0){
    		int sum = query(Qt[i].y)-query(Qt[i].x-1);
    		if(sumx?Mr:x;
        }
        for(int i=1,x,y,k;i<=m;i++){
            scanf("%s",opt);
            if(opt[0] == 'Q'){
                scanf("%d%d%d",&x,&y,&k);
                Qt[++cnt] = {x,y,k,++tot,1};//ask
            }else{
                scanf("%d%d",&x,&y);
                Qt[++cnt] = {a[x],0,0,x,-1};//delete
                Qt[++cnt] = {y,0,0,x,0};//insert
                a[x] = y;
            }
        }
        CDQ(Ml,Mr,1,cnt);
        for(int i=1;i<=tot;i++)printf("%d\n",ans[i]),ans[i] = 0;
    }
    return 0;
}

 

你可能感兴趣的:(模板类(什么,这也是模板))