【BZOJ】【P1176】【Balkan2007】【Mokia】【题解】【树状数组套平衡树】

传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=1176

我就不写分治你咬我呀

树状数组套平衡树感觉没什么好讲的

Code:

#include<cstdio>
#include<cctype>
#include<climits>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=2e6+5;
struct node{
	int val,key,sum,s;
	node *c[2];
	node(int _val=0,int _s=0,node *C=0){
		val=_val;key=rand();sum=s=_s;
		c[0]=c[1]=C;
	}
	void rz(){
		sum=c[0]->sum+s+c[1]->sum;
	}
}pool[maxn],*Null;
node *newnode(int _val=0,int _s=0,node *C=0){
	static int tot=0;
	if(tot<maxn){
		pool[tot].val=_val;
		pool[tot].key=rand();
		pool[tot].sum=pool[tot].s=_s;
		pool[tot].c[0]=pool[tot].c[1]=C;
		return &pool[tot++];
	}else return new node(_val,_s,C);
}
struct Treap{
	node *root;
	void init(){
		root=Null;
	}
	void rot(node *&t,bool d){
		node *p=t->c[d];t->c[d]=p->c[!d];
		p->c[!d]=t;t->rz();p->rz();t=p;
	}
	void insert(node *&t,int val,int s){
		if(t==Null){t=newnode(val,s,Null);return;}
		if(t->val==val){t->s+=s;t->sum+=s;return;}
		bool d=t->val<val;
		insert(t->c[d],val,s);
		if(t->c[d]->key<t->key)rot(t,d);
		else t->rz();
	}
	int Qsum(node *t,int x){
		int ans=0;
		while(t!=Null){
			if(t->val<=x)ans+=t->c[0]->sum+t->s,t=t->c[1];
			else t=t->c[0];
		}return ans;
	}
	void insert(int val,int s){insert(root,val,s);}
	int Qsum(int l,int r){return Qsum(root,r)-Qsum(root,l-1);}
};
inline int lowbit(int x){return x&-x;}
Treap d[maxn];
int get(int x1,int y1,int x2,int y2){
	int ans=0;x1--;
	while(x2)
	ans+=d[x2].Qsum(y1,y2),x2-=lowbit(x2);
	while(x1)
	ans-=d[x1].Qsum(y1,y2),x1-=lowbit(x1);
	return ans;
}
int w,s;
void updata(int x,int y,int s){
	while(x<=w){
		d[x].insert(y,s);
		x+=lowbit(x);
	}
}
int x,y,x1,y1,x2,y2,a;
int main(){
	Null=newnode(INT_MAX,0,0);
	Null->key=INT_MAX;Null->c[0]=Null->c[1]=Null;
	scanf("%d%d",&s,&w);int op;
	for(int i=1;i<=w;i++)d[i].init();
	while(scanf("%d",&op)!=-1){
		if(op==3)break;
		if(op==1){
			scanf("%d%d%d",&x,&y,&a);
			updata(x,y,a);
		}else{
			scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
			printf("%d\n",s*(x2-x1+1)*(y2-y1+1)+get(x1,y1,x2,y2)); 
		}
	}
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值