调了一整天拿20分求助
查看原帖
调了一整天拿20分求助
150611
mrozhx楼主2021/5/19 17:49

只A了前两个点,#5还T了,求大佬帮我看看

#include<bits/stdc++.h>
using namespace std;
#define ls (now<<1)
#define rs (ls|1)
#define mid ((l+r)>>1) 
const int N=100100,M=100100;
int n,m,rot=1,lit;
int a[N],id[N],nid[N],cnt[N],hea[N],dep[N],cap[N],fa[N];
int head[N],to[2*M],next[2*M],tot=0;
struct node{
	int mn,tag;
}tre[4*N];
void add(int x,int y){
	to[++tot]=y;
	next[tot]=head[x];
	head[x]=tot;
}
void dfs(int now){
	int ord=0;
	cnt[now]=1;//当前点有大小 
	for(int i=head[now];i;i=next[i]){
		int nxt=to[i];
		if(dep[nxt]) continue;
		fa[nxt]=now;//标记上一结点 
		dep[nxt]=dep[now]+1;//更新层数 
		dfs(nxt);//深搜 
		cnt[now]+=cnt[nxt];//更新当前子树大小 
		if(cnt[nxt]>cnt[ord]) ord=nxt;//更新最大子树 
	}
	hea[now]=ord;//最大子树 
}
void fhea(int now,int Fa){
	cap[nid[id[now]=++lit]=now]=Fa;//更新重链头、id、逆id 
	if(!hea[now]) return;//没有重后代即必为叶节点 
	fhea(hea[now],Fa);//优先重儿子,保证性质 
	for(int i=head[now];i;i=next[i]){
		int nxt=to[i];
		if(nxt==fa[now]||nxt==hea[now]) continue;//防止反向搜索 
		fhea(nxt,nxt);
	}
	return;
}
void pushup(int now){
	tre[now].mn=min(!tre[ls].mn?0x3f3f3f3f:tre[ls].mn,!tre[rs].mn?0x3f3f3f3f:tre[rs].mn);
}
void pushdown(int now){
	if(!tre[now].tag) return;
	tre[ls].mn=tre[ls].tag=tre[rs].mn=tre[rs].tag=tre[now].tag;
	tre[now].tag=0;
} 
void build(int now,int l,int r){
	if(l==r){
		tre[now].mn=a[nid[l]];
		return;
	}
	build(ls,l,mid);
	build(rs,mid+1,r);
	pushup(now);
}
void fix(int now,int l,int r,int L,int R,int num){
	if(L<=l&&r<=R){
		tre[now].mn=tre[now].tag=num;
		return;
	}
	pushdown(now);
	if(L<=mid) fix(ls,l,mid,L,R,num);
	if(R>mid) fix(rs,mid+1,r,L,R,num);
	pushup(now); 
}
void lik_fix(int fom,int to,int num){
	while(cap[fom]!=cap[to]){
		if(dep[cap[fom]]<dep[cap[to]]) swap(fom,to);
		fix(1,1,n,id[cap[fom]],id[fom],num);
		fom=fa[cap[fom]];
	}
	if(dep[fom]>dep[to]) swap(fom,to);
	fix(1,1,n,id[fom],id[to],num);
}
int query(int now,int l,int r,int L,int R){
	if(L>R) return 0x3f3f3f3f;
	int ans=0x3f3f3f3f;
	if(L<=l&&r<=R){
		return tre[now].mn;
	}
	pushdown(now);
	if(L<=mid) ans=min(ans,query(ls,l,mid,L,R));
	if(R>mid) ans=min(ans,query(rs,mid+1,r,L,R));
	pushup(now);
	return ans;
}
int lca(int x,int y){
	while(cap[x]!=cap[y]){
		if(dep[cap[x]]<dep[cap[y]]) swap(x,y);
		x=fa[cap[x]];
	}
	return dep[x]<dep[y]?x:y;
}
void rot_mn(int now,int nrot){
	int rel=lca(now,nrot),lst;
	if(now==nrot){
		printf("%d\n",tre[1].mn);
		return;
	}
	if(rel!=now){
		printf("%d\n",query(1,1,n,id[now],id[now]+cnt[now]-1));
	}
	else{
		int ans=0x3f3f3f3f;
		lst=nrot;
		while(fa[lst]!=now) if(dep[fa[cap[lst]]]>dep[now]) lst=fa[cap[lst]]; else lst=fa[lst];
//		printf("%d\n",min(query(1,1,n,id[rot],id[lst]-1),query(1,1,n,id[lst]+cnt[lst],id[rot]+cnt[rot]-1)));//除了nrot所在子树外,将整棵树的最小值统计一次 
		ans=query(1,1,n,1,id[lst]-1);
//		printf("%d %d %d		adsffadsf\n",lst,nrot,now);
		if(id[lst]+cnt[lst]-1!=n) ans=min(ans,query(1,1,n,id[lst]+cnt[lst],n));
		printf("%d\n",ans);
		/*now=lst;
		do{
			lst=now;
			now=fa[now];
			for(int i=head[now];i;i=next[i]){
				int nxt=to[i];
				if(nxt==lst||nxt==fa[now]) continue;
				ans=min(ans,query(1,1,n,id[nxt],id[nxt]+cnt[nxt]-1));
			}
			ans=min(ans,query(1,1,n,id[now],id[now]));
		}while(now!=rot);
		printf("%d\n",ans);*/
	}
} 
void check(int now,int l,int r){
	printf("%d %d %d\n",l,r,tre[now].mn);
	if(l==r) return;
	check(ls,l,mid);
	check(rs,mid+1,r);
}
int main(){
//	freopen("in.txt","r",stdin);
//	freopen("out.txt","w",stdout);
	int k,x,y,z,nrot;
	scanf("%d%d",&n,&m);
	for(int i=1;i<n;i++){
		scanf("%d%d",&x,&y);
		add(x,y);add(y,x);//加边 
	}
	for(int i=1;i<=n;i++){
		scanf("%d",&a[i]);
	}
	scanf("%d",&nrot);//结点间的相对位置是不变的,相当于最开始有一次操作1 
	dep[rot]=1;fa[rot]=rot;dfs(rot);//建树加各种标记+统计 
	fhea(rot,rot);//建链 
	build(1,1,n);//线段树统计链
//	check(1,1,n);
	for(int i=1,j=0;i<=m;i++){
		scanf("%d %d",&k,&x);
		if(k==1){
			nrot=x;
		}
		else if(k==2){
			scanf("%d%d",&y,&z);
			lik_fix(x,y,z);
		}
		else{
//			printf("%d    ",++j);
			rot_mn(x,nrot);
		}
	}
}
2021/5/19 17:49
加载中...