求助(30pts,树剖)
查看原帖
求助(30pts,树剖)
187086
whr080101楼主2020/10/6 10:35
//pair返回的均为<和,最大值> 
#include<bits/stdc++.h>
using namespace std;
const int MAXN=3e4+10;
inline bool id(const char ch) {
	return ch>='0'&&ch<='9';
} 
inline int read(void) {
	int s=0,f=1;
	char ch=getchar();
	while(!id(ch)) {
		if(ch=='-') f=-1;
		ch=getchar();
	}
	while(id(ch)) s=(s<<1)+(s<<3)+(ch^48),ch=getchar();
	return s*f;
}
struct Edge {
	int to,nxt;
}edge[MAXN*2];
int n,q;
int hd[MAXN],tot;
int size[MAXN],father[MAXN],dep[MAXN],son[MAXN],top[MAXN],seg[MAXN*4],rev[MAXN*4],ks;
int cnt[MAXN*4],v[MAXN*4],mx[MAXN*4],z[MAXN];
inline void add_edge(const int x,const int y) {
	edge[++tot]={y,hd[x]},hd[x]=tot;
	edge[++tot]={x,hd[y]},hd[y]=tot;
	return;
}
inline void dfs1(const int u,const int f) {  
	size[u]=1,father[u]=f,dep[u]=dep[f]+1; 
	for(int e=hd[u],v=edge[e].to;e;e=edge[e].nxt,v=edge[e].to) {
		if(v!=f) { 
			dfs1(v,u);
			size[u]+=size[v];
			if(size[v]>size[son[u]]) son[u]=v; 
		}
	}
	return;
}
inline void dfs2(const int u,const int f) {
	if(son[u]) { 
		seg[son[u]]=++seg[0],rev[seg[0]]=son[u]; 
		top[son[u]]=top[u];
		dfs2(son[u],u);
	}
	for(int e=hd[u],v=edge[e].to;e;e=edge[e].nxt,v=edge[e].to)
		if(!top[v]) {
			seg[v]=++seg[0],rev[seg[0]]=v;
			top[v]=v; 
			dfs2(v,u);
		}
	return;
}
inline void pushdown(const int k,const int l,const int r) { 
	int mid=(l+r)>>1;
	v[k<<1]+=cnt[k]*(mid-l+1),v[k<<1|1]+=cnt[k]*(r-mid);
	mx[k<<1]+=cnt[k],mx[k<<1|1]+=cnt[k];
	cnt[k<<1]+=cnt[k],cnt[k<<1|1]+=cnt[k],cnt[k]=0;
	return;
}
inline void update(const int k,const int l,const int r,const int x,const int y,const int z) {
	if(x<=l&&r<=y) {
		cnt[k]+=z,v[k]+=(r-l+1)*z,mx[k]+=z;
		return;
	}
	if(cnt[k]) pushdown(k,l,r);
	int mid=(l+r)>>1;
	if(mid>=x) update(k<<1,l,mid,x,y,z);
	if(y>mid) update(k<<1|1,mid+1,r,x,y,z);
	mx[k]=max(mx[k<<1],mx[k<<1|1]),v[k]=v[k<<1]+v[k<<1|1];
	return;
}
inline pair<int,int> query(const int k,const int l,const int r,const int x,const int y) {
	if(x<=l&&r<=y) return make_pair(v[k],mx[k]);
	if(cnt[k]) pushdown(k,l,r);
	int mid=(l+r)>>1,s=0,mx=-900000000-1;
	if(mid>=x) {
		pair<int,int> ks=query(k<<1,l,mid,x,y);
		s+=ks.first,mx=max(mx,ks.second);
	}
	if(y>mid) {
		pair<int,int> ks=query(k<<1|1,mid+1,r,x,y);
		s+=ks.first,mx=max(mx,ks.second);
	} 
	return make_pair(s,mx);
}
inline pair<int,int> ask(int u,int v) {
	int mx=-900000000-1,s=0,u1=0;
	while(top[u]!=top[v]) {
		if(dep[u]<dep[v]) swap(u,v);
		pair<int,int> k=query(1,1,n,seg[top[u]],seg[u]);
		if(top[u]==1) u1=1;
		u=father[top[u]],s+=k.first,mx=max(mx,k.second);
	}
	if(dep[u]<dep[v]) swap(u,v);
	pair<int,int> k=query(1,1,n,seg[v],seg[u]);
	if(!u1) s+=k.first,mx=max(mx,k.second);
	return make_pair(s,mx);
}
int main() {
	n=read();
	for(int i=1,u,v;i<n;i++) u=read(),v=read(),add_edge(u,v);
	for(int i=1,tmp;i<=n;i++) tmp=read(),z[i]=tmp;
	father[1]=1,top[1]=1,seg[1]=++seg[0],rev[seg[0]]=1;
	dfs1(1,1),dfs2(1,1);
	for(int i=1;i<=n;i++) update(1,1,n,seg[i],seg[i],z[i]);
	q=read();
	for(int i=1,u,v;i<=q;i++) {
		string tp;
		cin>>tp;
		u=read(),v=read();
		if(tp=="CHANGE") update(1,1,n,seg[u],seg[u],v-z[u]),z[u]=v;
		if(tp=="QMAX") printf("%d\n",ask(u,v).second);
		if(tp=="QSUM") printf("%d\n",ask(u,v).first);
	} 	
	return 0;
}

RT,树剖写炸了,可能是线段树?另外,我似乎处理不好两个点最终同时调到1的情况。HELP!

2020/10/6 10:35
加载中...