zoukankan      html  css  js  c++  java
  • [BZOJ 2683] 简单题 (CDQ分治)

    [BZOJ 2683] 简单题 (CDQ分治)

    题面

    N*N矩阵,支持单点修改,查询某一个子矩阵内的和

    (n leq 500000),操作数(leq 200000)

    分析

    首先运用二维前缀和的思想,把子矩阵的和拆成四个前缀和。

    然后把询问和修改看成(x,y,t)的三元组,t表示当前是第几次操作。然后就变成三维偏序问题,对于每个询问,找x,y,t均比它小的修改操作,再求和。

    代码

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define maxn 2000000
    #define maxm 2000000
    using namespace std;
    int n,m,cnt,qcnt;
    typedef int ll;
    struct node{
    	int a;//x
    	int b;//y
    	int c;//时间戳 
    	int type;//询问(2)还是修改(1) 
    	int val; //如果是修改,就是修改值。如果是询问,就是当前符号 
    	int id;//对应几号询问 
    	ll ans; 
    	node(){
    		
    	}
    	node(int _a,int _b,int _c,int _type,int _val){
    		a=_a;
    		b=_b;
    		c=_c;
    		type=_type;
    		val=_val;
    		id=ans=0;
    	}
    	node(int _a,int _b,int _c,int _type,int _val,int _id){
    		a=_a;
    		b=_b;
    		c=_c;
    		type=_type;
    		val=_val;
    		id=_id;
    		ans=0;
    	}
    }q[maxn+5];
    int cmpa(node p,node q){
    	if(p.a==q.a){
    		if(p.b==q.b) return p.c<q.c;
    		else return p.b<q.b;
    	}else return p.a<q.a;
    }
    int cmpb(node p,node q){
    	if(p.b==q.b) return p.c<q.c;
    	else return p.b<q.b;
    }
    
    struct fenwick_tree{
    	ll c[maxn+5];
    	inline int lowbit(int x){
    		return x&(-x);
    	}
    	inline void update(int pos,int val){
    		for(int i=pos;i<=maxn;i+=lowbit(i)) c[i]+=val;
    	}
    	inline ll query(int pos){
    		int ans=0;
    		for(int i=pos;i>0;i-=lowbit(i)) ans+=c[i];
    		return ans; 
    	}
    }T;
    node tmp[maxn+5];
    void cdq_divide(int l,int r){
    	int mid=(l+r)>>1;
    	if(l==r) return;
    	cdq_divide(l,mid);
    	cdq_divide(mid+1,r);
    //	sort(q+l,q+mid+1,cmpb);
    //	sort(q+mid+1,q+1+r,cmpb);
    	//这里不要大力sort,会TLE,回溯的时候合并就可以了
    	int ptr=l-1;
    	for(int i=mid+1;i<=r;i++){
    		while(ptr<mid&&q[ptr+1].b<=q[i].b){
    			ptr++;
    			if(q[ptr].type==1) T.update(q[ptr].c,q[ptr].val);
    		}
    		if(q[i].type==2) q[i].ans+=T.query(q[i].c);
    	} 
    	for(int i=l;i<=ptr;i++) if(q[i].type==1) T.update(q[i].c,-q[i].val);
    	int pl=l,pr=mid+1;
    	int num=l-1;
    	while(pl<=mid&&pr<=r){
    		if(cmpb(q[pl],q[pr])) tmp[++num]=q[pl++];
    		else tmp[++num]=q[pr++]; 
    	}
    	while(pl<=mid) tmp[++num]=q[pl++];
    	while(pr<=r) tmp[++num]=q[pr++];
    	for(int i=l;i<=r;i++) q[i]=tmp[i];
    }
    
    ll ans[maxn+5];
    int main(){
    	int cmd,x1,y1,x2,y2,v;
    	scanf("%d",&n);
    	while(1){
    		scanf("%d",&cmd);
    		if(cmd==1){
    			scanf("%d %d %d",&x1,&y1,&v);
    			m++;
    			q[++cnt]=node(x1,y1,m,1,v);
    		}else if(cmd==2){
    			scanf("%d %d %d %d",&x1,&y1,&x2,&y2);
    			m++;
    			qcnt++;
    			q[++cnt]=node(x2,y2,m,2,1,qcnt);
    			q[++cnt]=node(x1-1,y2,m,2,-1,qcnt);
    			q[++cnt]=node(x2,y1-1,m,2,-1,qcnt);
    			q[++cnt]=node(x1-1,y1-1,m,2,1,qcnt);
    		}else{
    			break;
    		} 
    	} 
    	sort(q+1,q+1+cnt,cmpa);
    	cdq_divide(1,cnt);
    	for(int i=1;i<=cnt;i++){
    		if(q[i].type==2){
    			ans[q[i].id]+=q[i].val*q[i].ans;
    		}
    	}
    	for(int i=1;i<=qcnt;i++) printf("%d
    ",ans[i]);
    } 
    
  • 相关阅读:
    查看文件 ls -lh
    java Dom4j xml 写
    centos tar 常用
    os && shutil 模块
    Visual Studio
    ssh 无法登陆
    find 命令
    Centos7 安装redis
    zerorpc
    uwsgi
  • 原文地址:https://www.cnblogs.com/birchtree/p/11366381.html
Copyright © 2011-2022 走看看