POJ 3468 A Simple Problem with Integers

我只是来练splay的…

照着kuangbin巨巨、cxlove巨巨的代码一点一点学习!


代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;
typedef long long LL;
#define keytree ch[ch[root][1]][0]
#define L(x) ch[x][0]
#define R(x) ch[x][1]
#define N 100010

int n,m,tot,root;
int a[N],ch[N][2],pre[N],size[N];
LL val[N],add[N],sum[N];

void newnode(int &u,int fa,int w)
{
	u=++tot;
	L(u)=R(u)=0;
	pre[u]=fa;
	size[u]=1;
	val[u]=w;
	add[u]=0;
}

void updatenode(int u,LL w)
{
	if(!u) return ;
	val[u]+=w;
	add[u]+=w;
	sum[u]+=w*size[u];
}

void up(int u)
{
	size[u]=size[L(u)]+size[R(u)]+1;
	sum[u]=sum[L(u)]+sum[R(u)]+val[u];
}

void down(int u)
{
	if(add[u])
	{
		updatenode(L(u),add[u]);
		updatenode(R(u),add[u]);
		add[u]=0;
	}
}

void rotate(int u,int kind)
{
	int fa=pre[u];
	down(fa);
	down(u);
	ch[fa][!kind]=ch[u][kind];
	pre[ch[u][kind]]=fa;
	if(pre[fa]) ch[pre[fa]][ch[pre[fa]][1]==fa]=u;
	pre[u]=pre[fa];
	ch[u][kind]=fa;
	pre[fa]=u;
	up(fa);
}

void splay(int u,int goal)
{
	int fa,kind;
	down(u);
	while(pre[u]!=goal)
	{
		if(pre[pre[u]]==goal) rotate(u,L(pre[u])==u);
		else
		{
			fa=pre[u];
			kind=L(pre[fa])==fa;
			if(ch[fa][kind]==u)
			{
				rotate(u,!kind);
				rotate(u,kind);
			}
			else
			{
				rotate(fa,kind);
				rotate(u,kind);
			}
		}
	}
	up(u);
	if(goal==0) root=u;
}

int getkth(int u,int k)
{
	down(u);
	int s=size[L(u)]+1;
	if(s==k) return u;
	if(s>k) return getkth(L(u),k);
	else return getkth(R(u),k-s);
}

void build(int &u,int l,int r,int fa)
{
	if(l>r) return ;
	int mid=(l+r)>>1;
	newnode(u,fa,a[mid]);
	build(L(u),l,mid-1,u);
	build(R(u),mid+1,r,u);
	up(u);
}

void init()
{
	root=tot=0;
	L(root)=R(root)=pre[root]=size[root]=val[root]=add[root]=sum[root]=0;
	newnode(root,0,-1);
	newnode(R(root),root,-1);
	build(keytree,1,n,R(root));
	up(R(root));
	up(root);
}

void update(int l,int r,int w)
{
	splay(getkth(root,l),0);
	splay(getkth(root,r+2),root);
	updatenode(keytree,w);
	up(R(root));
	up(root);
}

LL query(int l,int r)
{
	splay(getkth(root,l),0);
	splay(getkth(root,r+2),root);
	return sum[keytree];
}

int main()
{
	int u,v,x;
	char op[3];
	while(~scanf("%d%d",&n,&m))
	{
		for(u=1;u<=n;u++) scanf("%d",&a[u]);
		init();
		while(m--)
		{
			scanf("%s",op);
			if(op[0]=='Q')
			{
				scanf("%d%d",&u,&v);
				//cout<<query(u,v)<<endl;
				printf("%lld\n",query(u,v));
			}
			else
			{
				scanf("%d%d%d",&u,&v,&x);
				update(u,v,x);
			}
		}
	}
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值