zoukankan      html  css  js  c++  java
  • bzoj 1176: Mokia CDQ分治

    人生第一道自己写的CDQ LOL~~~

    题目大意

    维护一个W*W的矩阵,初始值均为S.每次操作可以增加某格子的权值,或询问某子矩阵的总权值.修改操作数M<=160000,询问数Q<=10000,W<=2000000.

    题解

    CDQ分治裸上啊...
    啥是CDQ啊?....
    怎么说呢..
    CDQ分治是一种思想.
    将整个序列分成两半递归处理,但是由于左边对右边的序列存在着不可忽略的影响,所以需要在递归时考虑左半边序列对右半边序列的影响。
    即CDQ的核心思想.(大概...)
    至于具体的实现过程,这种东西还是对着代码比较好学。

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    typedef long long ll;
    inline void read(int &x){
    	x=0;char ch;bool flag = false;
    	while(ch=getchar(),ch<'!');if(ch == '-') ch=getchar(),flag = true;
    	while(x=10*x+ch-'0',ch=getchar(),ch>'!');if(flag) x=-x;
    }
    const int maxm = 210010;
    const int maxn = 2100000;
    struct Node{
    	int op,x,y;
    	int val,id;
    	bool friend operator < (const Node &a,const Node &b){
    		return a.x < b.x;
    	}Node(){}
    	Node(int a,int b,int c,int d,int e){op=a;x=b;y=c;val=d;id = e;}
    }a[maxm],atmp[maxm];
    int cnt,n;
    int anss[10010];
    int c[maxn],tmp[maxm];
    #define lowbit(x) (x&-x)
    inline void modify(int x,int y){
    	if(!x) return;
    	for(;x <= n;x+=lowbit(x)) c[x] += y;
    }
    inline int query(int x){
    	int ret = 0;
    	for(;x>=1;x-=lowbit(x)) ret += c[x];
    	return ret;
    }
    inline void merge(int l,int r){
    	if(l == r) return;
    	int mid = l+r >> 1;
    	int i = l,j = mid+1,k = l;
    	while(i <= mid || j <= r){
    		if(j > r || ( i <= mid && a[i].x < a[j].x)) atmp[k++] = a[i++];
    		else atmp[k++] = a[j++];
    	}for(int i=l;i<=r;++i) a[i] = atmp[i];
    }
    void solve(int l,int r){//CDQ的分治
    	if(l == r) return ;
    	int mid = l+r >> 1;
    	solve(l,mid);//递归处理子序列
    	solve(mid+1,r);
    	merge(l,mid);//对左右序列分别排序
    	merge(mid+1,r);
    	//下面开始考虑左序列(中的插入操作)对右序列(中的询问操作)的影响
    	int p = l,cnt = 0;
    	for(int i = mid+1;i<=r;++i){
    		if(a[i].op == 2){//如果这是个询问操作
    			while(p <= mid && a[p].x <= a[i].x){
    				if(a[p].op == 1){//对于左序列所有的操作,更新影响
    					tmp[++cnt] = p;
    					modify(a[p].y,a[p].val);
    				}++p;
    			}anss[a[i].id] += a[i].val*query(a[i].y);//做出贡献
    		}
    	}
    	//清空树状数组,注意不能memset
    	for(int i=1;i<=cnt;++i) modify(a[tmp[i]].y,-a[tmp[i]].val);
    }
    int main(){
    	read(cnt);read(n);
    	int op,x1,y1,x2,y2,x;
    	int query_id = 0;
    	while(1){
    		read(op);if(op == 3) break;
    		if(op == 1){
    			read(x1);read(y1);read(x);
    			a[++cnt] = (Node){op,x1,y1,x,0};
    		}else{
    			x = ++query_id;
    			read(x1);read(y1);read(x2);read(y2);
    			//将所有的询问做成前缀和差分的形式
    			a[++cnt] = (Node){op,x2,y2,1,x};
    			a[++cnt] = (Node){op,x1-1,y2,-1,x};
    			a[++cnt] = (Node){op,x2,y1-1,-1,x};
    			a[++cnt] = (Node){op,x1-1,y1-1,1,x};
    		}
    	}
    	solve(1,cnt);
    	for(int i=1;i<=query_id;++i){
    		printf("%d
    ",anss[i]);
    	}
    	getchar();getchar();
    	return 0;
    }
    
  • 相关阅读:
    jmeter笔记5
    jmeter笔记4
    jmeter笔记3
    jmeter笔记2
    jmeter笔记1
    robot API笔记4
    robotframework笔记27
    robotframework笔记25
    robotframework笔记26
    robotframework笔记24
  • 原文地址:https://www.cnblogs.com/Skyminer/p/6403249.html
Copyright © 2011-2022 走看看