zoukankan      html  css  js  c++  java
  • BZOJ1176: [Balkan2007]Mokia

    BZOJ1176: [Balkan2007]Mokia

    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范围

    题解Here!

    矩阵上单点修改,区间查询,二维线段树就可以了。

    但是w<=2,000,000。

    而且我又不会cdq分治/K-D Tree。

    所以只能树状数组套Treap。

    将询问拆分一下即可。

    附代码:

    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #define MAXN 2000010
    using namespace std;
    int n;
    struct node{
    	node* son[2];
    	int v,w,x,sum;
    	node(){
    		son[0]=son[1]=NULL;
    		w=rand();
    		v=sum=x=0;
    	}
    };
    node* root[MAXN];
    inline int read(){
    	int date=0,w=1;char c=0;
    	while(c<'0'||c>'9'){if(c=='-')w=-1;c=getchar();}
    	while(c>='0'&&c<='9'){date=date*10+c-'0';c=getchar();}
    	return date*w;
    }
    inline void maintain(node* &u){
    	if(u==NULL)return;
    	u->sum=u->v;
    	if(u->son[0]!=NULL)u->sum+=u->son[0]->sum;
    	if(u->son[1]!=NULL)u->sum+=u->son[1]->sum;
    }
    inline void turn(node* &u,int f){
    	node* t=u->son[f^1];
    	u->son[f^1]=t->son[f];
    	t->son[f]=u;
    	maintain(u);
    	maintain(t);
    	u=t;
    }
    void insert(node* &u,int x,int v){
    	if(u==NULL){
    		u=new node;
    		u->x=x;
    		u->v=u->sum=v;
    		return;
    	}
    	else if(u->x==x){
    		u->v+=v;u->sum+=v;
    		return;
    	}
    	int y=u->x<x?1:0;
    	insert(u->son[y],x,v);
    	if(u->son[y]->w>u->w)turn(u,y^1);
    	maintain(u);
    }
    int query(node* u,int x){
    	int s=0;
    	while(u!=NULL){
    		if(u->x>x)u=u->son[0];
    		else{
    			if(u->son[0]!=NULL)s+=u->son[0]->sum;
    			s+=u->v;
    			u=u->son[1];
    		}
    	}
    	return s;
    }
    inline int lowbit(int x){return x&(-x);}
    inline void update(int x,int y,int v){
    	for(int i=x;i<=n;i+=lowbit(i))insert(root[i],y,v);
    }
    inline int sum(int x,int y){
    	int s=0;
    	for(int i=x;i;i-=lowbit(i))s+=query(root[i],y);
    	return s;
    }
    void work(){
    	while(1){
    		int f=read();
    		if(f==3)break;
    		if(f==1){
    			int x=read(),y=read(),k=read();
    			update(x,y,k);
    		}
    		else if(f==2){
    			int x1=read(),y1=read(),x2=read(),y2=read();
    			printf("%d
    ",sum(x2,y2)-sum(x1-1,y2)-sum(x2,y1-1)+sum(x1-1,y1-1));
    		}
    	}
    }
    void init(){
    	srand(987);
    	int x=read();
    	n=read();
    }
    int main(){
    	init();
    	work();
    	return 0;
    }
    
  • 相关阅读:
    virtualbox中ubuntu和windows共享文件夹设置
    嵌入式Linux USB WIFI驱动的移植
    U-boot mkimage指定Linux内核地址时的两种方式
    ramdisk作为根文件系统的配置
    ARM Linux系统的时钟机制
    ARM Linux 如何--注册和触发--软中断
    FAT32文件系统--For TF卡
    如何编写Linux设备驱动程序
    WiFi基本知识 .
    idea插件篇之java内存分析工具(JProfiler)
  • 原文地址:https://www.cnblogs.com/Yangrui-Blog/p/9369067.html
Copyright © 2011-2022 走看看