前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >hdu 3966 树链剖分 点操作

hdu 3966 树链剖分 点操作

作者头像
用户2965768
发布2019-08-29 10:13:49
2740
发布2019-08-29 10:13:49
举报
文章被收录于专栏:wymwym
代码语言:javascript
复制
/*by SilverN*/
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<cmath>
#define LL long long
using namespace std;
const int mxn=100010;
int read() {
	int x=0,f=1;
	char ch=getchar();
	while(ch<'0' || ch>'9') {
		if(ch=='-')f=-1;
		ch=getchar();
	}
	while(ch>='0' && ch<='9') {
		x=x*10+ch-'0';
		ch=getchar();
	}
	return x*f;
}
//读入优化
struct edge {
	int v,nxt;
} e[mxn<<1];
int hd[mxn],mct=0;
void add_edge(int u,int v) {
	e[++mct].v=v;
	e[mct].nxt=hd[u];
	hd[u]=mct;
}
//邻接表
struct node {
	//结点u的 父亲 重儿子
	int fa,son;
	int size,dep,top;//子树大小 深度 重链顶点
	int w,e;//编号 对应线段树的结尾
} tr[mxn];
//树剖结点
struct segtree {
	LL smm,mk;
} st[mxn<<2];
int sz=0;
//线段树
int n,M,rt;
int w[mxn];//初始值
//
void DFS1(int u) {
	tr[u].size=1;
	tr[u].son=0;
	for(int i=hd[u]; i; i=e[i].nxt) {
		int v=e[i].v;
		if(v==tr[u].fa)continue;
		tr[v].fa=u;
		tr[v].dep=tr[u].dep+1;
		DFS1(v);
		tr[u].size+=tr[v].size;
		if(tr[v].size>tr[tr[u].son].size)
			tr[u].son=v;
	}
	return;
}
void DFS2(int u,int top) { //当前点,当前链的顶点
	tr[u].top=top;
	tr[u].w=++sz;//把树边挂上线段树
	if(tr[u].son) {
		DFS2(tr[u].son,top);//扩展搭建重链
		for(int i=hd[u]; i; i=e[i].nxt) {
			int v=e[i].v;
			if(v!=tr[u].fa && v!=tr[u].son)
				DFS2(v,v);//搭建轻链
		}
	}
	tr[u].e=sz;//当前点对应的线段树结尾
	return;
}
void update(int L,int R,LL w,int l,int r,int k) { //区间加值
	if(L<=l && r<=R) {
		st[k].mk+=w;
		st[k].smm+=(r-l+1)*w;
		return;
	}
	int mid=(l+r)>>1;
	if(st[k].mk) {
		st[k<<1].mk+=st[k].mk;
		st[k<<1].smm+=st[k].mk*(mid-l+1);
		st[k<<1|1].mk+=st[k].mk;
		st[k<<1|1].smm+=st[k].mk*(r-mid);
		st[k].mk=0;
	}
	if(L<=mid)update(L,R,w,l,mid,k<<1);
	if(R>mid)update(L,R,w,mid+1,r,k<<1|1);
	st[k].smm=(st[k<<1].smm+st[k<<1|1].smm);
	return;
}
int query(int L,int R,int l,int r,int k) {
	if(L<=l && r<=R)return st[k].smm;
	int mid=(l+r)>>1;
	if(st[k].mk) {
		st[k<<1].mk+=st[k].mk;
		st[k<<1].smm+=st[k].mk*(mid-l+1);
		st[k<<1|1].mk+=st[k].mk;
		st[k<<1|1].smm+=st[k].mk*(r-mid);
		st[k].mk=0;
	}
	LL res=0;
	if(L<=mid)res=(res+query(L,R,l,mid,k<<1));
	if(R>mid)res=(res+query(L,R,mid+1,r,k<<1|1));
	return res;
}
// 表示求树从x到y结点最短路径上所有节点的值之和
int find(int x,int y) {
	int f1=tr[x].top,f2=tr[y].top;
	int ans=0;
	while(f1!=f2) {
		if(tr[f1].dep<tr[f2].dep) {
			ans+=query(tr[f2].w,tr[y].w,1,n,1);
			y=tr[f2].fa;
			f2=tr[y].top;
		} else {
			ans+=query(tr[f1].w,tr[x].w,1,n,1);
			x=tr[f1].fa;
			f1=tr[x].top;
		}
	}
	if(tr[x].dep<tr[y].dep)return ans+query(tr[x].w,tr[y].w,1,n,1);
	return ans+query(tr[y].w,tr[x].w,1,n,1);
}
void add(int x,int y,int k) { //x到y的路径加k
	int f1=tr[x].top,f2=tr[y].top;
	while(f1!=f2) {
		if(tr[f1].dep<tr[f2].dep) {
			update(tr[f2].w,tr[y].w,k,1,n,1);
			y=tr[f2].fa;
			f2=tr[y].top;
		} else {
			update(tr[f1].w,tr[x].w,k,1,n,1);
			x=tr[f1].fa;
			f1=tr[x].top;
		}
	}
	if(tr[x].dep<tr[y].dep) update(tr[x].w,tr[y].w,k,1,n,1);
	else update(tr[y].w,tr[x].w,k,1,n,1);
	return;
}
//
int main() {
	rt = 1;
	int q;
	while(scanf("%d %d %d",&n,&M,&q)==3) {
		int i,j;
		for(i=1; i<=n; i++) {
			w[i]=read();
		}
		int x,y,k;
		mct = 0; sz = 0;
		memset(hd,0,sizeof(hd));
		memset(st,0,sizeof(st));
		for(i=1; i<n; i++) {
			x=read();
			y=read();
			add_edge(x,y);
			add_edge(y,x);
		}
		sz=tr[0].size=tr[rt].dep=0;
		//
		DFS1(rt);
		DFS2(rt,rt);
		for(i=1; i<=n; i++)update(tr[i].w,tr[i].w,w[i],1,n,1);
		char op[15];
		for(i=1; i<=q; i++) {
			scanf("%s",op);
			if(op[0]=='I'){
				scanf("%d %d %d",&x,&y,&k);
				add(x,y,k);
			}else if(op[0]=='D'){
				scanf("%d %d %d",&x,&y,&k);
				add(x,y,-k);
			}else{
				scanf("%d",&x);
				printf("%d\n",query(tr[x].w,tr[x].w,1,n,1));
			}
		}
	}
	return 0;
}
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019年08月27日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档