[ZJOI2008]树的统计Count

130 篇文章 1 订阅
68 篇文章 0 订阅

被自己蠢哭了。

原来LCT即是在一开始的每个点输入一个点权的阶段也不能直接upd啊,还得Splay。。。。。。

LCT:

#include<cstdio>
#include<cstring>
#include<cctype>
#include<algorithm>
#define inf 0x3f3f3f3f
#define maxn 30005
using namespace std;

int n,m;
int fa[maxn],ch[maxn][2],Max[maxn],Sum[maxn],val[maxn];
bool rev[maxn],tp[maxn];
inline void upd(int now)
{ 
	Max[now]=max(max(Max[ch[now][0]],Max[ch[now][1]]),val[now]); 
	Sum[now]=Sum[ch[now][0]]+Sum[ch[now][1]]+val[now];
}
inline void dcd(int now)
{ 
	if(rev[now])
	{
		rev[now]=0;
		swap(ch[now][0],ch[now][1]);
		(ch[now][0]) && (rev[ch[now][0]] ^= 1);
		(ch[now][1]) && (rev[ch[now][1]] ^= 1);
	}
}

inline void Rotate(int x)
{
	if(!x || tp[x]) return;
	dcd(x);
	int y=fa[x],z=fa[y],c=(ch[y][1]==x);
	(ch[y][c]=ch[x][!c]) && (fa[ch[y][c]]=y);
	fa[fa[ch[x][!c]=y]=x]=z;
	if(!tp[y]) ch[z][ch[z][1]==y]=x;
	else swap(tp[y],tp[x]);
	swap(rev[y],rev[x]);
	upd(y),upd(x);	
}

void Splay(int x)
{
	dcd(x);
	for(int y;!tp[x];Rotate(x))
		if((y=fa[x]) && !tp[y])
			if((ch[y][1]==x)==(ch[fa[y]][1]==y)) Rotate(y);
			else Rotate(x);
	dcd(x);
}

int Access(int x)
{
	for(int y=0;;upd(x),y=x,x=fa[x])
	{
		if(!x) return y;
		Splay(x);
		(ch[x][1]) && (tp[ch[x][1]]=1);
		(ch[x][1]=y) && (tp[y]=0);
	}
}

void Bert(int x)
{
	Access(x),Splay(x);
	rev[x]^=1;dcd(x);
}

void Split(int x,int y){Bert(x),Access(y),Splay(y);}
void Change(int x,int w){ Splay(x),val[x]=w,upd(x); }
int Qmax(int x,int y){ Split(x,y);return Max[y]; }
int Qsum(int x,int y){ Split(x,y);return Sum[y]; };
void Link(int x,int y){ Bert(x),fa[x]=y; }

int main()
{
	
	//freopen("1.in","r",stdin);
	
	Sum[0]=0,Max[0]=-inf;
	scanf("%d",&n);
	memset(Max,-0x3f,sizeof Max);
	memset(tp,1,sizeof tp);
	memset(rev,0,sizeof rev);
	for(int i=1,u,v;i<n;i++)
	{
		scanf("%d%d",&u,&v);
		Link(u,v);
	}
	for(int i=1;i<=n;i++) 
		scanf("%d",&val[i]),
		Splay(i),upd(i);
	scanf("%d",&m);
	char ch[8];
	int u,v;
	for(;m--;)
	{
		scanf("%s%d%d",ch,&u,&v);
		if(ch[0]=='C') Change(u,v);
		else 
		{
			if(ch[1]=='M') printf("%d\n",Qmax(u,v));
			else printf("%d\n",Qsum(u,v));
		}
	}
}

树剖:

#include<cstdio>
#include<cstring>
#include<cctype>
#include<algorithm>
#define inf 0x3f3f3f3f
#define lc now<<1
#define rc now<<1|1
#define maxn 30005
using namespace std;

int n,m;
int info[maxn],Prev[maxn*2],to[maxn*2],cnt_e;
inline void Node(int u,int v){ Prev[++cnt_e]=info[u],info[u]=cnt_e ,to[cnt_e]=v;}

int dep[maxn],fa[maxn],tp[maxn],siz[maxn],son[maxn],id[maxn],cnt_id;
void dfs1(int now,int ff)
{
	dep[now]=dep[fa[now]=ff]+1;
	siz[now]=1,son[now]=-1;
	for(int i=info[now];i;i=Prev[i])
		if(to[i]!=ff)
		{
			dfs1(to[i],now);
			siz[now]+=siz[to[i]];
			(son[now]==-1 || siz[to[i]]>siz[son[now]]) && (son[now]=to[i]);
		}
}

void dfs2(int now,int ff,int anc)
{
	id[now]=++cnt_id,tp[now]=anc;
	if(son[now]!=-1) dfs2(son[now],now,anc);
	for(int i=info[now];i;i=Prev[i])
		if(to[i]!=ff && to[i]!=son[now])
			dfs2(to[i],now,to[i]);
}

int Max[maxn*10],Sum[maxn*10];

inline void upd(int now){ Max[now]=max(Max[lc],Max[rc]);Sum[now]=Sum[lc]+Sum[rc]; }

void Insert(int now,int l,int r,int pos,int val)
{
	if(l>pos || r<pos) return;
	if(l==r){ Max[now]=Sum[now]=val;return; }
	int mid=(l+r)>>1;
	Insert(lc,l,mid,pos,val);
	Insert(rc,mid+1,r,pos,val);
	upd(now);
}

int Qmax(int now,int l,int r,int ql,int qr)
{
	if(l>qr || r<ql) return -inf;
	if(ql<=l && r<=qr) return Max[now];
	int mid=(l+r)>>1;
	return max(Qmax(lc,l,mid,ql,qr),Qmax(rc,mid+1,r,ql,qr));
}

int Qsum(int now,int l,int r,int ql,int qr)
{
	if(l>qr || r<ql) return 0;
	if(ql<=l && r<=qr) return Sum[now];
	int mid=(l+r)>>1;
	return Qsum(lc,l,mid,ql,qr)+Qsum(rc,mid+1,r,ql,qr);
}

int Qmax(int u,int v)
{
	int ret=-inf;
	for(;tp[u]!=tp[v];)
	{
		if(dep[tp[u]]>dep[tp[v]]) swap(u,v);
		ret=max(ret,Qmax(1,1,n,id[tp[v]],id[v]));
		v=fa[tp[v]];
	}
	if(dep[u]>dep[v]) swap(u,v);
	return max(Qmax(1,1,n,id[u],id[v]),ret);
}

int Qsum(int u,int v)
{
	int ret=0;
	for(;tp[u]!=tp[v];)
	{
		if(dep[tp[u]]>dep[tp[v]]) swap(u,v);
		ret+=Qsum(1,1,n,id[tp[v]],id[v]);
		v=fa[tp[v]];
	}
	if(dep[u]>dep[v]) swap(u,v);
	return ret+Qsum(1,1,n,id[u],id[v]);
}

int main()
{	
	int u,v;
	char ch[8];
	
	scanf("%d",&n);
	for(int i=1;i<n;i++) scanf("%d%d",&u,&v),Node(u,v),Node(v,u);
	dfs1(1,0),dfs2(1,0,1);
	for(int i=1;i<=n;i++) scanf("%d",&u),Insert(1,1,n,id[i],u);
	scanf("%d",&m);
	for(;m--;)
	{
		scanf("%s%d%d",ch,&u,&v);
		if(ch[1]=='H') Insert(1,1,n,id[u],v);
		if(ch[1]=='M') printf("%d\n",Qmax(u,v));
		if(ch[1]=='S') printf("%d\n",Qsum(u,v));
 	}
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值