ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

树链剖分模板-2716-【ZJOI2008】树的统计

2020-06-18 20:06:00  阅读:233  来源: 互联网

标签:rt maxx ch 2716 剖分 int siz sum 树链


题目

    一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w。
  我们将以下面的形式来要求你对这棵树完成一些操作:
  I.CHANGE u t : 把结点u的权值改为t
  II.QMAX u v: 询问从点u到点v的路径上的节点的最大权值
  III.QSUM u v: 询问从点u到点v的路径上的节点的权值和
  注意:从点u到点v的路径上的节点包括u和v本身
  
  输入文件的第一行为一个整数n,表示节点的个数。
  接下来n–1行,每行2个整数a和b,表示节点a和节点b之间有一条边相连。
  接下来n行,每行一个整数,第i行的整数wi表示节点i的权值。
  接下来1行,为一个整数q,表示操作的总数。
  接下来q行,每行一个操作,以“CHANGE u t”或者“QMAX u v”或者“QSUM u v”的形式给出。
  对于100%的数据,保证1 <= n <= 30000,0 <= q <= 200000;中途操作中保证每个节点的权值w在-30000到30000之间。
  
Sample Input
4
1 2
2 3
4 1
4 2 1 3
12
QMAX 3 4
QMAX 3 3
QMAX 3 2
QMAX 2 3
QSUM 3 4
QSUM 2 1
CHANGE 1 5
QMAX 3 4
CHANGE 3 6
QMAX 3 4
QMAX 2 4
QSUM 3 4

Sample Output
4
1
2
2
10
6
5
6
5
16

#include <iostream>
#include <cstdio>
#include <algorithm>
#define maxn 100005
using namespace std;
int n,m;
int val[maxn],num[maxn],siz[maxn],ch[maxn][3],fa[maxn],maxx[maxn],sum[maxn],flag[maxn],cnt,root;
void pushup(int x)
{
	siz[x]=siz[ch[x][0]]+siz[ch[x][1]]+num[x];
	maxx[x]=val[x];
	if(ch[x][0]) maxx[x]=max(maxx[x],maxx[ch[x][0]]);
	if(ch[x][1]) maxx[x]=max(maxx[x],maxx[ch[x][1]]);
}
void pushdown(int x)
{
	if(!x) return;
	if(flag[x])
	{
		if(ch[x][0]){flag[ch[x][0]]^=1; swap(ch[ch[x][0]][0],ch[ch[x][0]][1]);}
		if(ch[x][1]){flag[ch[x][1]]^=1; swap(ch[ch[x][1]][0],ch[ch[x][1]][1]);}
		flag[x]=0;
	}
	if(sum[x])
	{
		if(ch[x][0]) sum[ch[x][0]]+=sum[x],val[ch[x][0]]+=sum[x],maxx[ch[x][0]]+=sum[x];
		if(ch[x][1]) sum[ch[x][1]]+=sum[x],val[ch[x][1]]+=sum[x],maxx[ch[x][1]]+=sum[x];
		sum[x]=0;
	}
}
void table()
{
	ch[1][1]=n+2; fa[n+2]=1;
	val[1]=0; val[n+2]=0;
	num[1]=num[n+2]=1; siz[1]=2; siz[n+2]=1;
	cnt=1; root=1;
}
void rot(int x,int &f)
{
	int y=fa[x],z=fa[y],l=(ch[y][0]!=x),r=(l^1);
	if(y==f) f=x;
	else ch[z][ch[z][1]==y]=x;
	fa[x]=z; fa[y]=x; fa[ch[x][r]]=y;
	ch[y][l]=ch[x][r]; ch[x][r]=y;
	pushup(y); pushup(x);
}
void splay(int x,int &f)
{
	while(x!=f)
	{
		int y=fa[x],z=fa[y];
		pushdown(z); pushdown(y); pushdown(x);
		if(y!=f){if(ch[z][0]==y^ch[y][0]==x) rot(x,f);else rot(y,f);}
		rot(x,f);
	}
}
int findk(int x,int rt)
{
	if(!x)return 0;
	pushdown(rt);int temp;
	if(siz[ch[rt][0]]+num[rt]>=x&&siz[ch[rt][0]]<x) temp=rt;
	else if(siz[ch[rt][0]]>=x) temp=findk(x,ch[rt][0]);
	else temp=findk(x-siz[ch[rt][0]]-num[rt],ch[rt][1]);
	pushup(rt);
	return temp;
}
int main()
{
	scanf("%d%d",&n,&m); table();
	for(int i=1;i<=n;++i)
	{
		int a=findk(i,root),b=findk(i+1,root);
		splay(a,root); splay(b,ch[a][1]);
		ch[b][0]=++cnt; num[cnt]=siz[cnt]=1; fa[cnt]=b;
		pushup(cnt); pushup(b); pushup(a);
	}
	cnt=n+2;
	while(m--)
	{
		int f1,f2,f3,f4; scanf("%d",&f1);
		if(f1==1)
		{
			scanf("%d%d%d",&f2,&f3,&f4);
			int a=findk(f2,root),b=findk(f3+2,root);
			splay(a,root); splay(b,ch[a][1]);
			sum[ch[b][0]]+=f4; val[ch[b][0]]+=f4; maxx[ch[b][0]]+=f4;
			pushup(b); pushup(a);
	
		}
		else if(f1==2)
		{
			scanf("%d%d",&f2,&f3);int a=findk(f2,root),b=findk(f3+2,root);
			splay(a,root); splay(b,ch[a][1]);
			flag[ch[b][0]]^=1;
			swap(ch[ch[b][0]][0],ch[ch[b][0]][1]);
		}
		else if(f1==3)
		{
			scanf("%d%d",&f2,&f3);int a=findk(f2,root),b=findk(f3+2,root);
			splay(a,root); splay(b,ch[a][1]);
			printf("%d\n",maxx[ch[b][0]]);
		}
	}
	return 0;
}

标签:rt,maxx,ch,2716,剖分,int,siz,sum,树链
来源: https://www.cnblogs.com/wuwendongxi/p/13159520.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有