萌新刚学树剖,TLE2个点 求助
查看原帖
萌新刚学树剖,TLE2个点 求助
169861
模拟王子楼主2021/8/26 20:38

从模板题复制来打的

救救孩子,TLE 7,8!!!!

#include<cstdio>
#include<iostream>
#define int long long
using namespace std;
struct node{
	int to,next;
}edge[600001];
struct node1{
	int l,r,num,sum,flag,maxn;
}t[400001];
char s[101];
int maxn;
int ans;
int cntt,fa1[1000001],tot,head[1000001],cnt1,m,n,R,res,wt[1000001];
int w[10000001],id[1000001],size[1000001],depth[1000001],heavyson[1000001],top[1000001];
int inline read()
{
	int x=0,f=1;
	char ch;ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch<='9' && ch>='0')
	{
		x=x*10+ch-'0';
		ch=getchar();
	}
	return x*f;
}
void addedge(int u,int v)
{
	edge[++cnt1].to=v;
	edge[cnt1].next=head[u];
	head[u]=cnt1;
}
void maketree(int tot,int l,int r)
{
	t[tot].l=l;
	t[tot].r=r;
	if(l==r)
	{
		t[tot].sum=wt[l];
		t[tot].maxn=wt[l];
		return ;
	}
	int mid=(l+r)>>1;
	maketree(tot<<1,l,mid);
	maketree(tot<<1|1,mid+1,r);
	t[tot].sum=(t[tot<<1].sum+t[tot<<1|1].sum);
	t[tot].maxn=max(t[tot<<1].maxn,t[tot<<1|1].maxn);
}
void down(int tot,int l,int r)  // 标记下移 
{  	
	t[tot<<1].flag+=t[tot].flag;  
	t[tot<<1|1].flag+=t[tot].flag;  
	int mid=(l+r)/2;
	t[tot<<1|1].sum+=(mid-l+1)*t[tot].flag;  //!!!!注意先加 
	t[tot<<1|1].sum+=(r-mid)*t[tot].flag;  
	t[tot].flag=0;  
}
void change(int tot,int l,int r,int x,int y,int z)   //区间更改 
{
	if(l>=x && r<=y)  
	{  
		t[tot].sum=(r-l+1)*z;
		t[tot].maxn=z;
		t[tot].flag+=z;
		return ;  
	}  
	if(t[tot].flag)	down(tot,l,r);
	int mid=(l+r)>>1;  
	if(x<=mid) //在左区间  
		change(tot<<1,l,mid,x,y,z);  
	if(y>mid) // 在右区间 
		change(tot<<1|1,mid+1,r,x,y,z);  
	t[tot].sum=(t[tot<<1].sum+t[tot<<1|1].sum); 
	t[tot].maxn=max(t[tot<<1].maxn,t[tot<<1|1].maxn); 
}
void ask(int tot,int l,int r,int x,int y)
{
	if(l>=x && r<=y)
	{
		res+=t[tot].sum;
		return ;
	}
	if(t[tot].flag) down(tot,l,r);
	int mid=(l+r)>>1;
	if(x<=mid) ask(tot<<1,l,mid,x,y);
	if(y>mid)  ask(tot<<1|1,mid+1,r,x,y);
}
void ask2(int tot,int l,int r,int x,int y)
{
	if(l>=x && r<=y)
	{
		maxn=max(maxn,t[tot].maxn);
		return ;
	}
	if(t[tot].flag)	down(tot,l,r);
	int mid=(l+r)/2;
	if(x<=mid) ask2(tot<<1,l,mid,x,y);
	if(y>mid)  ask2(tot<<1|1,mid+1,r,x,y);
}
///////////////////////// 以上为线段树部分 
void dfs1(int u,int fa)  // 找重儿子 
{
	fa1[u]=fa; // 父亲节点 
	depth[u]=depth[fa]+1;
	int heavy=0;
	size[u]=1;
	for(int i=head[u];i;i=edge[i].next)
	{
		int v=edge[i].to;
		if(v!=fa)
		{
			dfs1(v,u);
			size[u]+=size[v];
			if(size[u]>heavy)
			{
				heavyson[u]=v;
				heavy=size[u];
			}
		}
	}
}
void dfs2(int u,int k)
{ 
	top[u]=k; 	// 找到链头顶端 
	id[u]=++cntt; // 每个节点新编号 
	wt[cntt]=w[u];  //把每个点的初始值赋到新编号上来 
	if(heavyson[u]) dfs2(heavyson[u],k); // 优先遍历重儿子 
	for(int i=head[u];i;i=edge[i].next)
	{
		int v=edge[i].to;
		if(v==fa1[u] || v==heavyson[u]) continue;
		dfs2(v,v);
	}
}
void get1(int x,int y)
{
	maxn=-0x7fffffff;
	while(top[x]!=top[y]) // 不在同一条链上 
	{	
		if(depth[top[x]]<depth[top[y]]) swap(x,y);
		ask2(1,1,n,id[top[x]],id[x]);
		x=fa1[top[x]];
	}
	if(depth[x]>depth[y]) swap(x,y); // 在同一条链 此时x的深度比y小 
	ask2(1,1,n,id[x],id[y]);
	printf("%lld\n",maxn);
}
void get2(int x,int y)
{
	ans=0; 
	while(top[x]!=top[y]) // 不在同一条链上 
	{
		if(depth[top[x]]<depth[top[y]])  swap(x,y); // 把x改为深度更深的点 
		res=0;
		ask(1,1,n,id[top[x]],id[x]); // ans加上x点到x所在链顶端 这一段区间的点权和
		ans+=res;
		x=fa1[top[x]];
	}
	//直到两个点处于一条链上
	if(depth[x]>depth[y]) swap(x,y);
	res=0;
	ask(1,1,n,id[x],id[y]);
	ans+=res;
	printf("%lld\n",ans);
}
void get3(int x,int y)
{
	change(1,1,n,id[x],id[x],y);	
}
signed main()
{
	n=read();
	for(int i=1;i<n;i++){int u,v;u=read();v=read();addedge(u,v);addedge(v,u);}
	for(int i=1;i<=n;++i)
	w[i]=read();
	dfs1(1,0);
	dfs2(1,1);
	maketree(1,1,n);
	m=read();
	for(int i=1;i<=m;i++)
	{
		int k,x,y,z;
		cin>>s;
		if(s[0]=='C'){x=read();y=read();get3(x,y);}
		if(s[0]=='Q' && s[1]=='M') {x=read();y=read();get1(x,y);}
		if(s[0]=='Q' && s[1]=='S') {x=read();y=read();get2(x,y);}
	}
	return 0;
}
2021/8/26 20:38
加载中...