题目传送门
这题实际上如果你把他的温度看做边权的话,那么实际上这题就是要你动态维护最大生成树,这个东西用边权LCT做就行了。至于边权LCT是什么,可以自行百度学习学习啦(光速逃)..
#pragma GCC optimize(3,"Ofast","inline")
#include
using namespace std;
typedef long long ll;
bool Finish_read;
template<class T>inline void read(T &x){Finish_read=0;x=0;int f=1;char ch=getchar();while(!isdigit(ch)){if(ch=='-')f=-1;if(ch==EOF)return;ch=getchar();}while(isdigit(ch))x=x*10+ch-'0',ch=getchar();x*=f;Finish_read=1;}
template<class T>inline void print(T x){if(x/10!=0)print(x/10);putchar(x%10+'0');}
template<class T>inline void writeln(T x){if(x<0)putchar('-');x=abs(x);print(x);putchar('\n');}
template<class T>inline void write(T x){if(x<0)putchar('-');x=abs(x);print(x);}
/*================Header Template==============*/
const int maxn=400005,inf=0x3f3f3f3f;
struct Edge {
int u,v;
Edge(int u=0,int v=0):u(u),v(v){}
}edges[maxn];
namespace LCT {
struct Node {
int fa,dis,val,rev,len,Min,ch[2];
Node(int fa=0,int dis=0,int val=inf,int rev=0,int len=0,int Min=inf):fa(fa),dis(dis),val(val),rev(rev),len(len),Min(Min){ch[0]=ch[1]=0;}
inline int& operator [] (int y) {
return this->ch[y];
}
}T[maxn];
inline void Reverse(int x) {
swap(T[x][0],T[x][1]);
T[x].rev^=1;
}
inline void Pushup(int x) {
T[x].len=T[x].dis,T[x].Min=T[x].val;
if(T[x][0])
T[x].len+=T[T[x][0]].len,T[x].Min=min(T[x].Min,T[T[x][0]].Min);
if(T[x][1])
T[x].len+=T[T[x][1]].len,T[x].Min=min(T[x].Min,T[T[x][1]].Min);
}
inline void Pushdown(int x) {
if(T[x].rev) {
if(T[x][0])
Reverse(T[x][0]);
if(T[x][1])
Reverse(T[x][1]);
T[x].rev^=1;
}
}
inline bool Isroot(int x) {
return T[T[x].fa][0]!=x&&T[T[x].fa][1]!=x;
}
inline void Pushtag(int x) {
if(!Isroot(x))
Pushtag(T[x].fa);
Pushdown(x);
}
inline int Isright(int x) {
return T[T[x].fa][1]==x;
}
inline void Rotate(int x) {
int y=T[x].fa,z=T[y].fa,r=Isright(x),l=r^1;
if(!Isroot(y))
T[z][Isright(y)]=x;
T[x].fa=z,T[y].fa=x;
T[T[x][l]].fa=y;
T[y][r]=T[x][l];
T[x][l]=y;
Pushup(y),Pushup(x);
}
inline void Splay(int x) {
Pushtag(x);
while(!Isroot(x)) {
int y=T[x].fa;
if(!Isroot(y)) {
if(Isright(x)==Isright(y))
Rotate(y);
else
Rotate(x);
}
Rotate(x);
}
}
inline void Access(int x) {
int t=0;
for(;x;t=x,x=T[x].fa)
Splay(x),T[x][1]=t,Pushup(x);
}
inline void Makeroot(int x) {
Access(x),Splay(x),Reverse(x);
}
inline void Link(int x,int y) {
Makeroot(x),Makeroot(y),T[x].fa=y;
}
inline void Cut(int x,int y) {
Makeroot(x),Access(y),Splay(y),T[y][0]=T[x].fa=0,Pushup(y);
}
inline int Getfa(int x) {
while(T[x].fa)
x=T[x].fa;
return x;
}
}
using namespace LCT;
int n,q,ty,id,u,v,t,l;
char s[10];
unordered_map<int,int>Bel;
inline void Addedge(int id,int u,int v,int t,int l) {
edges[id]=Edge(u,v);
Bel[t]=id;
int x=id+n;
T[x].dis=l,T[x].val=t;
Pushup(x),Link(x,u),Link(x,v);
}
inline void Deledge(int id) {
int u=edges[id].u,v=edges[id].v,x=id+n;
Cut(x,u),Cut(x,v);
}
int main() {
read(n),read(q);
while(q--) {
scanf("%s",s);
if(s[0]=='f') {
read(id),read(u),read(v),read(t),read(l);
id++,u++,v++;
Makeroot(u),Makeroot(v);
if(Getfa(u)!=Getfa(v))
Addedge(id,u,v,t,l);
else {
Makeroot(u),Access(v),Splay(v);
int Min=T[v].Min;
if(t>Min) {
Deledge(Bel[Min]);
Addedge(id,u,v,t,l);
}
}
}
if(s[0]=='m') {
read(u),read(v),++u,++v;
Makeroot(u),Makeroot(v);
if(Getfa(u)!=Getfa(v))
puts("-1");
else {
Makeroot(u),Access(v),Splay(v);
printf("%d\n",T[v].len);
}
}
if(s[0]=='c') {
read(id),read(l),++id;
int x=id+n;
Makeroot(x),T[x].dis=l,Pushup(x);
}
}
}