码迷,mamicode.com
首页 > 其他好文 > 详细

[UOJ274]温暖会指引我们前行

时间:2018-02-15 20:45:29      阅读:186      评论:0      收藏:0      [点我收藏+]

标签:down   play   void   维护   ...   swa   lin   std   --   

看春晚不如写题...

第一次写维护边权的题,因为懒所以没学边权lct,写的是插入虚点存边权,但我猜两种写法的效率应该差不多

要求最低温度尽量高,所以只能走最高温度生成树上的边,用lct维护就行了

lct维护最大生成树,每加一条边$\left(x,y,T\right)$,如果两边不连通就直接连,如果连通且树上$x\rightarrow y$的最低温度$\geq T$,那么不用加边,否则删掉树上路径最低温的边,加入新边

个人觉得这种插入虚点维护边权的写法挺方便的

#include<stdio.h>
int ch[400010][2],fa[400010],r[400010],t[400010],l[400010],mn[400010],mp[400010],s[400010];
#define ls ch[x][0]
#define rs ch[x][1]
void pushup(int x){
	s[x]=s[ls]+s[rs]+l[x];
	mn[x]=t[x];
	mp[x]=x;
	if(ls&&mn[ls]<mn[x]){
		mn[x]=mn[ls];
		mp[x]=mp[ls];
	}
	if(rs&&mn[rs]<mn[x]){
		mn[x]=mn[rs];
		mp[x]=mp[rs];
	}
}
void swap(int&a,int&b){a^=b^=a^=b;}
void rev(int x){
	r[x]^=1;
	swap(ls,rs);
}
void pushdown(int x){
	if(r[x]){
		if(ls)rev(ls);
		if(rs)rev(rs);
		r[x]=0;
	}
}
bool isrt(int x){return ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x;}
void gao(int x){
	if(!isrt(x))gao(fa[x]);
	pushdown(x);
}
void rot(int x){
	int y,z,f,B;
	y=fa[x];
	z=fa[y];
	f=(ch[y][0]==x);
	B=ch[x][f];
	fa[x]=z;
	fa[y]=x;
	if(B)fa[B]=y;
	ch[x][f]=y;
	ch[y][f^1]=B;
	if(ch[z][0]==y)ch[z][0]=x;
	if(ch[z][1]==y)ch[z][1]=x;
	pushup(y);
	pushup(x);
}
void splay(int x){
	int y,z;
	gao(x);
	while(!isrt(x)){
		y=fa[x];
		z=fa[y];
		if(!isrt(y))rot((ch[z][0]==y&&ch[y][0]==x)||(ch[z][1]==y&&ch[y][1]==x)?y:x);
		rot(x);
	}
}
void access(int x){
	int y=0;
	while(x){
		splay(x);
		rs=y;
		pushup(x);
		y=x;
		x=fa[x];
	}
}
void makert(int x){
	access(x);
	splay(x);
	rev(x);
}
bool cn(int x,int y){
	if(x==y)return 1;
	makert(x);
	access(y);
	splay(y);
	return fa[x]!=0;
}
void link(int x,int y){
	makert(x);
	fa[x]=y;
}
void modify(int x,int v){
	splay(x);
	l[x]=v;
	pushup(x);
}
int query(int x,int y){
	if(!cn(x,y))return-1;
	makert(x);
	access(y);
	splay(y);
	return s[y];
}
int querymin(int x,int y){
	makert(x);
	access(y);
	splay(y);
	return mn[y];
}
void cutmin(int x,int y){
	makert(x);
	access(y);
	splay(y);
	x=mp[y];
	splay(x);
	fa[ls]=fa[rs]=0;
}
void link(int id,int x,int y,int T,int L){
	if(cn(x,y)){
		if(querymin(x,y)>=T)return;
		cutmin(x,y);
	}
	mn[id]=t[id]=T;
	s[id]=l[id]=L;
	mp[id]=id;
	link(x,id);
	link(id,y);
}
int main(){
	int n,m,i,u,v,t,l;
	char s[10];
	scanf("%d%d",&n,&m);
	for(i=1;i<=n;i++)mn[i]=::t[i]=1000000000;
	while(m--){
		scanf("%s",s);
		if(s[0]==‘f‘){
			scanf("%d%d%d%d%d",&i,&u,&v,&t,&l);
			i++;
			u++;
			v++;
			link(i+n,u,v,t,l);
		}
		if(s[0]==‘m‘){
			scanf("%d%d",&u,&v);
			u++;
			v++;
			printf("%d\n",query(u,v));
		}
		if(s[0]==‘c‘){
			scanf("%d%d",&i,&l);
			i++;
			modify(i+n,l);
		}
	}
}

[UOJ274]温暖会指引我们前行

标签:down   play   void   维护   ...   swa   lin   std   --   

原文地址:https://www.cnblogs.com/jefflyy/p/8449773.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!