zoukankan      html  css  js  c++  java
  • 【刷题】洛谷 P1501 [国家集训队]Tree II

    题目描述

    一棵n个点的树,每个点的初始权值为1。对于这棵树有q个操作,每个操作为以下四种操作之一:

    • + u v c:将u到v的路径上的点的权值都加上自然数c;

    • - u1 v1 u2 v2:将树中原有的边(u1,v1)删除,加入一条新边(u2,v2),保证操作完之后仍然是一棵树;

    • * u v c:将u到v的路径上的点的权值都乘上自然数c;

    • / u v:询问u到v的路径上的点的权值和,求出答案对于51061的余数。

    输入输出格式

    输入格式:

    第一行两个整数n,q

    接下来n-1行每行两个正整数u,v,描述这棵树

    接下来q行,每行描述一个操作

    输出格式:

    对于每个/对应的答案输出一行

    输入输出样例

    输入样例#1:

    3 2
    1 2
    2 3
    * 1 3 4
    / 1 1

    输出样例#1:

    4

    说明

    10%的数据保证,1<=n,q<=2000

    另外15%的数据保证,1<=n,q<=5*10^4,没有-操作,并且初始树为一条链

    另外35%的数据保证,1<=n,q<=5*10^4,没有-操作

    100%的数据保证,1<=n,q<=105,0<=c<=104

    By (伍一鸣)

    题解

    这个题类似模板,只是变成了维护加法和乘法
    类似于维护线段数时的加法和乘法
    维护乘法时,要乘维护的和,点的权值和加法的lazy标记
    维护加法的话,就直接加就行了
    (这道题我有个地方少打了个=号,结果找了一个半小时。。)

    #include<bits/stdc++.h>
    #define ll long long
    #define db double
    #define ld long double
    #define lc(x) ch[(x)][0]
    #define rc(x) ch[(x)][1]
    const int MAXN=100000+10,Mod=51061;
    ll n,q,Val[MAXN];
    struct LCT{
    	ll ch[MAXN][2],fa[MAXN],rev[MAXN],size[MAXN],sum[MAXN],add[MAXN],mul[MAXN];
    	inline void init()
    	{
    		for(register int i=1;i<=n;++i)Val[i]=size[i]=sum[i]=mul[i]=1;
    		memset(ch,0,sizeof(ch));
    		memset(fa,0,sizeof(fa));
    		memset(rev,0,sizeof(rev));
    	}
    	inline bool nroot(ll x)
    	{
    		return rc(fa[x])==x||lc(fa[x])==x;
    	}
    	inline void reverse(ll x)
    	{
    		std::swap(lc(x),rc(x));
    		rev[x]^=1;
    	}
    	inline void plus(ll x,ll k)
    	{
    		(Val[x]+=k)%=Mod;
    		(sum[x]+=size[x]*k%Mod)%Mod;
    		(add[x]+=k)%=Mod;
    	}
    	inline void multi(ll x,ll k)
    	{
    		(Val[x]*=k)%=Mod;
    		(sum[x]*=k)%=Mod;
    		(add[x]*=k)%=Mod;(mul[x]*=k)%=Mod;
    	}
    	inline void pushup(ll x)
    	{
    		size[x]=size[lc(x)]+size[rc(x)]+1;
    		sum[x]=(sum[lc(x)]+sum[rc(x)]+Val[x])%Mod;
    	}
    	inline void pushdown(ll x)
    	{
    		if(mul[x]!=1)
    		{
    			multi(lc(x),mul[x]);multi(rc(x),mul[x]);
    			mul[x]=1;
    		}
    		if(add[x])
    		{
    			plus(lc(x),add[x]);plus(rc(x),add[x]);
    			add[x]=0;
    		}
    		if(rev[x])
    		{
    			if(lc(x))reverse(lc(x));
    			if(rc(x))reverse(rc(x));
    			rev[x]=0;
    		}
    	}
    	inline void rotate(ll x)
    	{
    		ll f=fa[x],p=fa[f],c=(rc(f)==x);
    		if(nroot(f))ch[p][rc(p)==f]=x;
    		fa[ch[f][c]=ch[x][c^1]]=f;
    		fa[ch[x][c^1]=f]=x;
    		fa[x]=p;
    		pushup(f);
    		pushup(x);
    	}
    	inline void splay(ll x)
    	{
    		std::stack<ll> s;
    		s.push(x);
    		for(register int i=x;nroot(i);i=fa[i])s.push(fa[i]);
    		while(!s.empty())pushdown(s.top()),s.pop();
    		for(register int y=fa[x];nroot(x);rotate(x),y=fa[x])
    			if(nroot(y))rotate((lc(y)==x)==(lc(fa[y])==y)?y:x);
    		pushup(x);
    	}
    	inline void access(ll x)
    	{
    		for(register ll y=0;x;x=fa[y=x])splay(x),rc(x)=y,pushup(x);
    	}
    	inline void makeroot(ll x)
    	{
    		access(x);splay(x);reverse(x);
    	}
    	inline void split(ll x,ll y)
    	{
    		makeroot(x);access(y);splay(y);
    	}
    	inline void link(ll x,ll y)
    	{
    		makeroot(x);fa[x]=y;
    	}
    	inline void cut(ll x,ll y)
    	{
    		split(x,y);fa[x]=lc(y)=0;pushup(y);
    	}
    };
    LCT T;
    template<typename T> inline void read(T &x)
    {
    	T data=0,w=1;
    	char ch=0;
    	while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
    	if(ch=='-')w=-1,ch=getchar();
    	while(ch>='0'&&ch<='9')data=((T)data<<3)+((T)data<<1)+(ch^'0'),ch=getchar();
    	x=data*w;
    }
    template<typename T> inline void write(T x,char c='')
    {
    	if(x<0)putchar('-'),x=-x;
    	if(x>9)write(x/10);
    	putchar(x%10+'0');
    	if(c!='')putchar(c);
    }
    template<typename T> inline void chkmin(T &x,T y){x=(y<x?y:x);}
    template<typename T> inline void chkmax(T &x,T y){x=(y>x?y:x);}
    template<typename T> inline T min(T x,T y){return x<y?x:y;}
    template<typename T> inline T max(T x,T y){return x>y?x:y;}
    int main()
    {
    	read(n);read(q);
    	T.init();
    	for(register int i=1;i<n;++i)
    	{
    		ll u,v;
    		read(u);read(v);
    		T.link(u,v);
    	}
    	while(q--)
    	{
    		char opt;
    		std::cin>>opt;
    		if(opt=='+')
    		{
    			ll u,v,c;
    			read(u);read(v);read(c);
    			T.split(u,v);T.plus(v,c);
    		}
    		if(opt=='*')
    		{
    			ll u,v,c;
    			read(u);read(v);read(c);
    			T.split(u,v);T.multi(v,c);
    		}
    		if(opt=='/')
    		{
    			ll u,v;
    			read(u);read(v);
    			T.split(u,v);
    			write(T.sum[v],'
    ');
    		}
    		if(opt=='-')
    		{
    			ll u1,v1,u2,v2;
    			read(u1);read(v1);read(u2);read(v2);
    			T.cut(u1,v1);T.link(u2,v2);
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    数据绑定表达式语法(Eval,Bind区别)
    使用博客园的第一件事 自定义主题
    sql2000 跨服务器复制表数据
    使用UpdatePanel 局部刷新出现中文乱码的解决方法!!
    MMC不能打开文件MSC文件
    sql 日期 、时间相关
    loaded AS2 swf call function in AS3 holder
    Rewrite the master page form action attribute in asp.net 2.0
    100万个不重复的8位的随机数
    flash 中实现斜切变型
  • 原文地址:https://www.cnblogs.com/hongyj/p/8688060.html
Copyright © 2011-2022 走看看