zoukankan      html  css  js  c++  java
  • BZOJ_2683_简单题&&BZOJ_1176_[Balkan2007]Mokia_CDQ分治+树状数组

    BZOJ_2683_简单题&&BZOJ_1176_[Balkan2007]Mokia_CDQ分治+树状数组

    Description

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

    Input

    第一行两个整数,S,W;其中S为矩阵初始值;W为矩阵大小

    接下来每行为一下三种输入之一(不包含引号):

    "1 x y a"

    "2 x1 y1 x2 y2"

    "3"

    输入1:你需要把(x,y)(第x行第y列)的格子权值增加a

    输入2:你需要求出以左下角为(x1,y1),右上角为(x2,y2)的矩阵内所有格子的权值和,并输出

    输入3:表示输入结束

    Output

    对于每个输入2,输出一行,即输入2的答案

    Sample Input

    0 4
    1 2 3 3
    2 1 1 3 3
    1 2 2 2
    2 2 2 3 4
    3

    Sample Output

    3
    5

    HINT

    保证答案不会超过int范围


    S=min(max(S,0),0)

    把询问拆成4个矩形查询(1,1)->(x,y)的权值和。

    然后有三维信息:时间,x轴,y轴。

    处理左边,处理右边,然后处理左边的修改操作对右边查询操作的影响。

    按x轴归并上去。

    代码:

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    #define N 200050
    int W,n,T[2000050],m,ans[N];
    struct A {
    	int x,y,opt,c,id;
    }a[N],tmp[N];
    void fix(int x,int v) {
    	for(;x<=W;x+=x&(-x)) T[x]+=v;
    }
    int inq(int x) {
    	int re=0;
    	for(;x;x-=x&(-x)) re+=T[x];
    	return re;
    }
    void solve(int l,int r) {
    	if(l==r) return ;
    	int mid=(l+r)>>1;
    	solve(l,mid); solve(mid+1,r);
    	int j=l,k=mid+1,i=l;
    	while(j<=mid&&k<=r) {
    		if(a[j].x<=a[k].x) {
    			if(a[j].opt==0) fix(a[j].y,a[j].c); tmp[i++]=a[j++];
    		}else {
    			if(a[k].opt==1) ans[a[k].id]+=a[k].c*inq(a[k].y); tmp[i++]=a[k++];
    		}
    	}
    	while(j<=mid) {
    		if(a[j].opt==0) fix(a[j].y,a[j].c); tmp[i++]=a[j++];
    	}
    	while(k<=r) {
    		if(a[k].opt==1) ans[a[k].id]+=a[k].c*inq(a[k].y); tmp[i++]=a[k++];
    	}
    	for(i=l;i<=mid;i++) {
    		if(a[i].opt==0) fix(a[i].y,-a[i].c);
    	}
    	for(i=l;i<=r;i++) a[i]=tmp[i];
    }
    int main() {
    	scanf("%*d%d",&W);
    	int opt,x,y,z,w;
    	while(1) {
    		scanf("%d",&opt);
    		if(opt==3) break;
    		if(opt==1) {
    			scanf("%d%d%d",&x,&y,&z);
    			a[++n]=(A){x,y,0,z,0};
    		}else {
    			m++;
    			scanf("%d%d%d%d",&x,&y,&z,&w); x--; y--;
    			a[++n]=(A){z,w,1,1,m};
    			a[++n]=(A){z,y,1,-1,m};
    			a[++n]=(A){x,w,1,-1,m};
    			a[++n]=(A){x,y,1,1,m};
    		}
    	}
    	solve(1,n);
    	int i;
    	for(i=1;i<=m;i++) printf("%d
    ",ans[i]);
    }
    
  • 相关阅读:
    pl/sql可以封装代码的结构(过程,函数, 包)
    pl/sql 块结构
    Oracle 逻辑模型(数据库,用户的关系)
    Oracle 创建用户为什么要加C##
    CentOS8断电后无法正常启动
    Cannot open /var/log/sa/sa26: No such file or directory
    Centos6.6安装sysstat报错/etc/cron.d
    Oracle DBCA工具检测不到ASM磁盘组
    Redis安装
    Mysql模拟故障恢复案例过程
  • 原文地址:https://www.cnblogs.com/suika/p/9202469.html
Copyright © 2011-2022 走看看