您的位置:首页 > 其它

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

2018-02-15 20:26 399 查看
看春晚不如写题...

第一次写维护边权的题,因为懒所以没学边权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);
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐