zoukankan      html  css  js  c++  java
  • CDQ分治小结

    CDQ分治小结

    P3810三维偏序(陌上花开)

    一道CDQ分治的比较模板又不是模板的问题.

    (f_i)表示(a_j<=a_i)(b_j<=b_i)(c_j<=c_i)(j)的数量

    对于(din[0,n))让你求(f(i) == d)的数量

    其实个人感觉模板的话

    还是严格小于比较好做

    先来考虑一下严格小于该怎么做

    我们先对整体按照(a_i)排序,这样的话我们进行的分治就满足了第一个限制

    之后我们试想一下,如果要求左区间对于右区间的贡献

    我们只需要将两边分别排序

    虽然这样两边就不一定在满足(a_i)的限制,但是左右两个区间依旧满足(因为我们是分别排序)

    直接用权值树状数组计算右边对与左边的贡献

    但是,如果要求小于等于,就要考虑有两个值其(a_I,b_i,c_i)均相同的情况

    这样的话我们就去重

    将重复(n)个的元素的权值改为(n)

    最后

    (cnt_{ai.ans + ai.val-1}+=ai.ans)

    即可

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #include<cctype>
    #include<queue>
    #include<stack>
    using namespace std;
    const int N = 1e5 + 3;
    const int M = 2e5 + 3;
    int n,k;
    struct BIT{
    	int c[M];
    	inline int lowbit(int x){return x & -x;}
    	inline void ins(int x,int v){
    		for(;x <= k;x += lowbit(x)) c[x] += v;
    	}
    	inline int query(int x){
    		int res = 0;
    		for(;x;x -= lowbit(x)) res += c[x];
    		return res;	
    	}
    }T;
    struct node{
    	int x,y,z;
    	int val,ans;	
    }a[N],b[N];
    int cnt[N];
    inline int read(){
    	char ch = getchar();int v = 0,c = 1;
    	while(!isdigit(ch)){
    		if(ch == '-') c = -1;
    		ch = getchar();	
    	}
    	while(isdigit(ch)){
    		v = v * 10 + ch - 48;
    		ch = getchar();	
    	}
    	return v * c;	
    }
    inline bool cmpx(node xx,node yy){
    	if(xx.x != yy.x)
    	return xx.x < yy.x;
    	if(xx.y != yy.y)
    	return xx.y < yy.y;
    	return xx.z < yy.z;
    }
    inline bool cmpy(node xx,node yy){
    	if(xx.y != yy.y)
    	return xx.y < yy.y;
    	return xx.z < yy.z;
    }	
    inline void solve(int l,int r){
    	if(l == r) return ;
    	int mid = (l + r) >> 1;
    	solve(l,mid);solve(mid + 1,r);
    //	printf("l:%d r:%d
    ",l,r);
    	sort(a + l,a + mid + 1,cmpy);
    	sort(a + mid + 1,a + r + 1,cmpy);
    //	for(int i = l;i <= r;++i) printf("%d %d
    ",a[i].y,a[i].z);
    	int top = l;
    	for(int i = mid + 1;i <= r;++i){
    		for(;top <= mid && a[top].y <= a[i].y;top++)
    		T.ins(a[top].z,a[top].val);
    	//	printf("%d %d %d
    ",top,i,T.query(a[i].z));
    		a[i].ans += T.query(a[i].z);
    	}
    	for(int i = l;i < top;++i) T.ins(a[i].z,-a[i].val);
    }
    int main(){
    	n = read(),k = read();
    	for(int i = 1;i <= n;++i)
    		b[i].x = read(),b[i].y = read(),b[i].z = read();
    	sort(b + 1,b + n + 1,cmpx);
    	int c = 0,num = 0;
    	for(int i = 1;i <= n;++i){
    		c++;
    		if(b[i].x != b[i + 1].x || b[i].y != b[i + 1].y || b[i].z != b[i + 1].z)
    		a[++num] = b[i],a[num].val = c,c = 0;
    	}
    	swap(num,n);//for(int i = 1;i <= n;++i) printf("%d %d %d %d
    ",a[i].x,a[i].y,a[i].z,a[i].val);
    	solve(1,n);
    //	for(int i = 1;i <= n;++i) printf("%d ",a[i].ans);puts("");
    	for(int i = 1;i <= n;++i) cnt[a[i].ans + a[i].val - 1] += a[i].val;
    	for(int i = 0;i < num;++i) printf("%d
    ",cnt[i]);
    	return 0;	
    }
    

    CF669E. Little Artem and Time Machine

    CDQ的板子题了

    我们以输入的操作顺序为第一维

    操作的时间为第二维

    第三维就直接查询有多少数等于他就好了

    但是由于排序是将

    sort(a + l,a + mid + 1,cmp)
    

    写成了

    sort(a + l + 1,a + mid + 1,cmp)
    

    然后,调了一下午,还去找(wqy)学长丢人

    #include<cstdio>
    #include<cstring>
    #include<cctype>
    #include<map>
    #include<algorithm>
    #include<iostream>
    #define LL long long
    using namespace std;
    const int N = 1e5 + 3;
    int n;
    struct Q{
    	int type;
    	LL time;
    	LL val;
    	int id;
    	int ans;
    }a[N];
    map <LL,int> m;
    inline LL read(){
    	char ch = getchar();long long v = 0,c = 1;
    	while(!isdigit(ch)){
    		if(ch == '-') c = -1;
    		ch = getchar();	
    	}
    	while(isdigit(ch)){
    		v = v * 10 + ch - 48;
    		ch = getchar();	
    	}
    	return v * c;	
    }
    inline bool cmp(Q x,Q y){
    	return x.time < y.time;	
    }
    inline bool cmp2(Q x,Q y){
    	return x.id < y.id;
    }
    inline void solve(int l,int r){
    	if(l == r) return ;
    	int mid = (l + r) >> 1;
    	solve(l,mid);solve(mid + 1,r);
    //	printf("l:%d r:%d
    ",l,r);
    	sort(a + l,a + mid + 1,cmp);
    	sort(a + mid + 1,a + r + 1,cmp);
    //	for(int i = l;i <= mid;++i) printf("%d %lld %lld
    ",a[i].type,a[i].time,a[i].val);
    //	printf("---------------
    ");
    //	for(int i = mid + 1;i <= r;++i) printf("%d %lld %lld
    ",a[i].type,a[i].time,a[i].val);
    	int top = l;
    	for(int i = mid + 1;i <= r;++i){
    		while(i <= r && a[i].type != 3) ++i;
    		if(i > r) break;
    		while(top <= mid && a[top].time <= a[i].time){
    			if(a[top].type == 1) m[a[top].val]++;
    			else if(a[top].type == 2) m[a[top].val]--;
    			top++;
    		}
    		a[i].ans += m[a[i].val];
    	}
    	m.clear();
    }
    int main(){
    	n = read();
    	for(int i = 1;i <= n;++i){
    		a[i].type = read();
    		a[i].time = read();
    		a[i].val = read();
    		a[i].id = i;
    	}
    	solve(1,n);
    	sort(a + 1,a + n + 1,cmp2); 
    	for(int i = 1;i <= n;++i) if(a[i].type == 3) printf("%d
    ",a[i].ans);
    	return 0;	
    
  • 相关阅读:
    WINCE创建快捷方式
    Android初级开发第四讲系统中一些属性的区别
    Android初级开发第六讲Activity的布局
    Android初级开发第三讲项目中控件的学习
    物联网产业链及市场分
    读《浪潮之巅》有感
    Hello China V1.75成功运行于Lenovo超级本上
    Android初级开发第七讲特效和数据传递处理
    Android中级第二讲制作搜索页面,使用TextWatcher
    电信运营商物联网实践建议
  • 原文地址:https://www.cnblogs.com/wyxdrqc/p/10853818.html
Copyright © 2011-2022 走看看