zoukankan      html  css  js  c++  java
  • 树链剖分【p2590】[ZJOI2008]树的统计

    Description

    一棵树上有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本身

    Input

    输入文件的第一行为一个整数n,表示节点的个数。

    接下来n – 1行,每行2个整数a和b,表示节点a和节点b之间有一条边相连。

    接下来一行n个整数,第i个整数wi表示节点i的权值。

    接下来1行,为一个整数q,表示操作的总数。

    接下来q行,每行一个操作,以“CHANGE u t”或者“QMAX u v”或者“QSUM u v”的形式给出。

    Output

    对于每个“QMAX”或者“QSUM”的操作,每行输出一个整数表示要求输出的结果。

    树剖裸题 刷水题吼啊

    这题是一个裸的点权,不用转边权做.大水题

    单点修改,(tag)都不用打.qwq

    线段树维护区间最大值,区间和。

    单点修改要对(dfn)修改!! (本来要切掉的,结果这里写错了.

    代码

    #include<cstdio>
    #include<cstdlib>
    #include<iostream>
    #include<cstring>
    #define int long long
    #define R register
    #define ls o<<1
    #define rs o<<1|1
    #define N 30008
    using namespace std;
    inline void in(int &x)
    {
    	int f=1;x=0;char s=getchar();
    	while(!isdigit(s)){if(s=='-')f=-1;s=getchar();}
    	while(isdigit(s)){x=x*10+s-'0';s=getchar();}
    	x*=f;
    }
    int head[N],tot,depth[N],size[N],f[N],son[N];
    struct cod{int u,v;}edge[N<<1];
    int dfn[N],idx,fdfn[N],top[N];
    int n,a[N],m,tr[N<<2],mx[N<<2];
    char s[18];
    inline void add(int x,int y)
    {
    	edge[++tot].u=head[x];
    	edge[tot].v=y;
    	head[x]=tot;
    }
    inline void up(int o)
    {
    	tr[o]=tr[ls]+tr[rs];
    	mx[o]=max(mx[ls],mx[rs]);
    }
    void build(int o,int l,int r)
    {
    	if(l==r)
    	{
    		mx[o]=tr[o]=a[fdfn[l]];
    		return;
    	}
    	int mid=(l+r)>>1;
    	build(ls,l,mid);
    	build(rs,mid+1,r);
    	up(o);
    }
    int query_sum(int o,int l,int r,int x,int y)
    {
    	if(x<=l and y>=r)return tr[o];
    	int mid=(l+r)>>1,res=0;
    	if(x<=mid)res+=query_sum(ls,l,mid,x,y);
    	if(y>mid)res+=query_sum(rs,mid+1,r,x,y);
    	return res;
    }
    int query_max(int o,int l,int r,int x,int y)
    {
    	if(x<=l and y>=r)return mx[o];
    	int mid=(l+r)>>1,res=-2147483647;
    	if(x<=mid)res=max(res,query_max(ls,l,mid,x,y));
    	if(y>mid)res=max(res,query_max(rs,mid+1,r,x,y));
    	return res;
    }
    void change(int o,int l,int r,int pos,int k)
    {
    	if(l==r){mx[o]=tr[o]=k;return;}
    	int mid=(l+r)>>1;
    	if(pos<=mid)change(ls,l,mid,pos,k);
    	else change(rs,mid+1,r,pos,k);
    	up(o);
    }
    void dfs1(int u,int fa)
    {
    	size[u]=1;f[u]=fa;depth[u]=depth[fa]+1;
    	for(R int i=head[u];i;i=edge[i].u)
    	{
    		if(edge[i].v==fa)continue;
    		dfs1(edge[i].v,u);
    		size[u]+=size[edge[i].v];
    		if(son[u]==-1 or size[son[u]]<size[edge[i].v])
    			son[u]=edge[i].v;
    	}
    }
    void dfs2(int u,int t)
    {
    	dfn[u]=++idx;fdfn[idx]=u;top[u]=t;
    	if(son[u]==-1)return;
    	dfs2(son[u],t);
    	for(R int i=head[u];i;i=edge[i].u)
    	{
    		if(dfn[edge[i].v])continue;
    		dfs2(edge[i].v,edge[i].v);
    	}
    }
    int tquery(int x,int y)
    {
    	int fx=top[x],fy=top[y],res=0;
    	while(fx!=fy)
    	{
    		if(depth[fx]>depth[fy])
    		{
    			res+=query_sum(1,1,idx,dfn[fx],dfn[x]);
    			x=f[fx];
    		}
    		else
    		{
    			res+=query_sum(1,1,idx,dfn[fy],dfn[y]);
    			y=f[fy];
    		}
    		fx=top[x],fy=top[y];
    	}
    	if(dfn[x]>dfn[y])swap(x,y);
    	res+=query_sum(1,1,idx,dfn[x],dfn[y]);
    	return res;
    }
    int tquery_max(int x,int y)
    {
    	int fx=top[x],fy=top[y],res=-2147483647;
    	while(fx!=fy)
    	{
    		if(depth[fx]>depth[fy])
    		{
    			res=max(res,query_max(1,1,idx,dfn[fx],dfn[x]));
    			x=f[fx];
    		}
    		else
    		{
    			res=max(res,query_max(1,1,idx,dfn[fy],dfn[y]));
    			y=f[fy];
    		}
    		fx=top[x],fy=top[y];
    	}
    	if(dfn[x]>dfn[y])swap(x,y);
    	res=max(res,query_max(1,1,idx,dfn[x],dfn[y]));
    	return res;
    }
    signed main()
    {
    	in(n);memset(son,-1,sizeof son);
    	for(R int i=1,x,y;i<n;i++)
    	{
    		in(x),in(y);
    		add(x,y);add(y,x);
    	}
    	dfs1(1,0);dfs2(1,1);
    	for(R int i=1;i<=n;i++)in(a[i]);
    	build(1,1,n);
    	in(m);
    	for(R int x,y;m;m--)
    	{
    		scanf("%s",s);in(x),in(y);
    		if(s[3]=='X')
    			printf("%lld
    ",tquery_max(x,y));
    		else if(s[3]=='M')
    			printf("%lld
    ",tquery(x,y));
    		else
    			change(1,1,idx,dfn[x],y);
    	}
    }
    
  • 相关阅读:
    unity 3d 之合并网格和贴图(combine mesh and texture)
    哈希表(散列表)原理详解
    二叉树-你必须要懂!(二叉树相关算法实现-iOS)
    浅谈数据结构-二叉树
    python中的日志操作和发送邮件
    python实现自定义接口
    python 操作excel
    两个redis之间迁移的python实现
    python对redis的连接和操作
    python3导入自定义模块
  • 原文地址:https://www.cnblogs.com/-guz/p/9798223.html
Copyright © 2011-2022 走看看