寒冬又一次肆虐了北国大地
无情的北风穿透了人们御寒的衣物
可怜虫们在冬夜中发出无助的哀嚎
“冻死宝宝了!”
这时
远处的天边出现了一位火焰之神
“我将赐予你们温暖和希望!”
只见他的身体中喷射出火焰之力
通过坚固的钢铁,传遍了千家万户
这时,只听见人们欢呼
“暖气来啦!”
任务描述
虽然小R住的宿舍楼早已来了暖气,但是由于某些原因,宿舍楼中的某些窗户仍然开着(例如厕所的窗户),这就使得宿舍楼中有一些路上的温度还是很低。
小R的宿舍楼中有nn个地点和一些路,一条路连接了两个地点,小R可以通过这条路从其中任意一个地点到达另外一个地点。但在刚开始,小R还不熟悉宿舍楼中的任何一条路,所以他会慢慢地发现这些路,他在发现一条路时还会知道这条路的温度和长度。每条路的温度都是互不相同的。
小R需要在宿舍楼中活动,每次他都需要从一个地点到达另一个地点。小R希望每次活动时经过一条最温暖的路径,最温暖的路径的定义为,将路径上各条路的温度从小到大排序后字典序最大。即温度最低的路温度尽量高,在满足该条件的情况下,温度第二低的路温度尽量高,以此类推。小R不会经过重复的路。由于每条路的温度互不相同,因此只存在一条最温暖的路径。
对于小R的每次活动,你需要求出小R需要走过的路径总长度。如果小R通过当前发现的路不能完成这次活动,则输出 −1−1。
注意本题中的字典序与传统意义上的字典序定义有所不同,对于两个序列a,b(a≠b)a,b(a≠b),若aa是bb的前缀则aa的字典序较大,同时可以推出空串的字典序最大。
输入格式
第一行两个正整数 n,mn,m。表示小R的宿舍楼中有 nn 个地点,共发生了 mm 个事件。
接下来 mm 行,每行描述一个事件,事件分为三类。
-
find id u v t lfind id u v t l 表示小R发现了一条连接uu和vv之间的路,编号为idid。相同idid的边只会出现一次。
-
move u vmove u v 表示小R要从uu到达vv,你需要计算出最温暖的路径的长度 ,若不能从uu到达vv,则输出−1−1。
-
change id lchange id l 表示从uu到vv这条边的长度变为了ll(保证在当前时间点这条边存在)。
输出格式
对于每个询问,输出一行整数,表示最温暖的路径长度。
样例一
input
8 19 find 0 0 2 7 2 find 1 2 4 4 4 find 2 4 6 10 1 find 3 6 7 8 6 move 2 7 move 1 6 find 4 2 5 3 4 move 0 5 change 0 12 find 5 4 5 5 10 find 6 2 3 6 9 move 3 5 find 7 0 1 12 1 move 1 6 find 8 1 7 11 100 move 1 6 move 3 7 move 5 6 move 2 2
output
11 -1 6 23 18 106 122 11 0
样例二
input
15 45 find 0 1 0 8 5987 find 1 2 0 14 5455 find 2 3 0 27 8830 find 3 4 3 42 7688 find 4 5 0 25 1756 find 5 6 5 35 1550 find 6 7 4 43 9440 move 3 9 change 2 9113 move 10 13 move 3 3 move 11 10 find 7 8 7 6 7347 find 8 9 8 26 8935 move 8 4 change 3 4466 find 9 10 9 28 8560 move 6 5 find 10 11 10 31 6205 change 9 9228 find 11 12 10 23 948 find 12 13 12 45 5945 move 0 9 move 2 5 change 2 6118 find 13 14 13 12 6906 move 4 1 change 2 504 find 14 4 2 22 9796 move 10 7 move 1 14 move 13 3 find 15 12 9 39 8985 find 16 9 8 17 3710 change 1 5370 find 17 1 0 36 4669 find 18 7 6 37 8087 move 9 0 find 19 14 9 33 8234 find 20 0 4 24 5209 change 1 4883 find 21 6 3 9 2461 find 22 5 2 19 4291 change 1 7219 change 6 4846
output
-1 -1 0 -1 16787 1550 39301 7211 16571 25510 59706 46309 30692
样例三
见样例数据下载
限制与约定
对于find操作:(0≤id<m,0≤u,v<n,u≠v,0≤t≤1000000000,0≤l≤10000)(0≤id<m,0≤u,v<n,u≠v,0≤t≤1000000000,0≤l≤10000);
对于move操作:(0≤u,v<n)(0≤u,v<n);
对于change操作:(0≤l≤10000)(0≤l≤10000)。
对于100%的数据,1≤n≤100000,1≤m≤3000001≤n≤100000,1≤m≤300000 。
本题共有20个数据点,每个数据点5分。
测试点 | nn | mm | 其它其它 |
---|---|---|---|
1−21−2 | ≤20≤20 | ≤50≤50 | 无特殊约定 |
3−53−5 | ≤1000≤1000 | ≤3000≤3000 | |
6−106−10 | ≤100000≤100000 | ≤300000≤300000 | 所有的find事件都在move事件之前,且没有change事件 |
11−1411−14 | 所有的find事件都在move事件之前 | ||
15−2015−20 | 无特殊约定 |
时间限制:2s2s
空间限制:512MB
树 动态生成树 LCT
题意看着麻烦,其实就是动态维护最大生成树
二十分钟敲完,脑抽写错cut调了一小时
就很气。
第119行:断边的时候,当然要断那条边和它的原端点,然而一开始写成了断目标边和现在要加的边的端点。←蠢
代码调来调去变得各种慢,失去了观赏价值(说得仿佛原来有价值一样)
1 /*by SilverN*/ 2 #include<algorithm> 3 #include<iostream> 4 #include<cstring> 5 #include<cstdio> 6 #include<cmath> 7 #include<vector> 8 using namespace std; 9 const int INF=0x3f3f3f3f; 10 const int mxn=400010; 11 int read(){ 12 int x=0,f=1;char ch=getchar(); 13 while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();} 14 while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();} 15 return x*f; 16 } 17 struct edge{ 18 int x,y,m; 19 }e[mxn]; 20 int id[mxn]; 21 struct node{ 22 int ch[mxn][2],fa[mxn]; 23 bool rev[mxn]; 24 // 25 int tmp[mxn],val[mxn],smm[mxn]; 26 int mi[mxn],mipos[mxn]; 27 // 28 int st[mxn],top; 29 inline bool isroot(int x){return (ch[fa[x]][0]!=x && ch[fa[x]][1]!=x);} 30 void PD(int x){ 31 if(rev[x]){ 32 int &lc=ch[x][0],&rc=ch[x][1]; 33 swap(lc,rc); 34 rev[lc]^=1; rev[rc]^=1; 35 rev[x]^=1; 36 } 37 return; 38 } 39 void pushup(int x){ 40 int lc=ch[x][0],rc=ch[x][1]; 41 smm[x]=smm[lc]+smm[rc]+val[x]; 42 mi[x]=tmp[x],mipos[x]=x; 43 if(mi[lc]<mi[x]){mi[x]=mi[lc];mipos[x]=mipos[lc];} 44 if(mi[rc]<mi[x]){mi[x]=mi[rc];mipos[x]=mipos[rc];} 45 return; 46 } 47 void rotate(int &x){ 48 int y=fa[x],z=fa[y],lc,rc; 49 if(ch[y][0]==x)lc=0;else lc=1; rc=lc^1; 50 if(!isroot(y)){ch[z][ch[z][1]==y]=x;} 51 fa[x]=z;fa[y]=x;fa[ch[x][rc]]=y; 52 ch[y][lc]=ch[x][rc]; 53 ch[x][rc]=y; 54 pushup(y); 55 return; 56 } 57 void Splay(int x){ 58 st[top=1]=x; 59 for(int i=x;!isroot(i);i=fa[i])st[++top]=fa[i]; 60 while(top)PD(st[top--]); 61 while(!isroot(x)){ 62 int y=fa[x],z=fa[y]; 63 if(!isroot(y)){ 64 if((ch[y][0]==x)^(ch[z][0]==y))rotate(x); 65 else rotate(y); 66 } 67 rotate(x); 68 } 69 pushup(x); 70 return; 71 } 72 void access(int x){ 73 for(int y=0;x;x=fa[x]){ 74 Splay(x); 75 ch[x][1]=y; 76 pushup(x); 77 y=x; 78 } 79 return; 80 } 81 void mkroot(int x){ 82 access(x);Splay(x); 83 rev[x]^=1; 84 return; 85 } 86 int find(int x){ 87 access(x);Splay(x); 88 while(ch[x][0])x=ch[x][0]; 89 return x; 90 } 91 inline void link(int x,int y){ 92 mkroot(x);fa[x]=y; 93 return; 94 } 95 void cut(int x,int y){ 96 mkroot(x); 97 access(y); 98 Splay(y); 99 if(ch[y][0]==x){fa[x]=0;ch[y][0]=0;} 100 pushup(y); 101 return; 102 } 103 void change(int x,int l){ 104 access(x);Splay(x); 105 val[x]=l; 106 pushup(x); 107 return; 108 } 109 int query(int x,int y){ 110 if(find(x)!=find(y))return -1; 111 mkroot(x);access(y);Splay(y); 112 return smm[y]; 113 } 114 void add(int u,int v,int x){ 115 if(find(u)==find(v)){ 116 query(u,v); 117 if(mi[v]>=tmp[x])return; 118 int tar=mipos[v]; 119 cut(e[id[tar]].x,tar);cut(tar,e[id[tar]].y); 120 } 121 link(u,x);link(x,v); 122 return; 123 } 124 }Lt; 125 int n,m,cnt; 126 char op[30]; 127 int main(){ 128 int i,j,u,v,w,l; 129 n=read();m=read(); 130 for(i=0;i<=n;i++){ 131 Lt.tmp[i]=Lt.mi[i]=INF; 132 Lt.val[i]=Lt.val[i]=0; 133 Lt.mipos[i]=i; 134 } 135 cnt=n; 136 for(i=1;i<=m;i++){ 137 scanf("%s",op); 138 switch(op[0]){ 139 case 'f':{ 140 ++cnt;j=read(); 141 id[cnt]=j;u=read()+1;v=read()+1;w=read();l=read(); 142 e[j].x=u;e[j].y=v;e[j].m=cnt; 143 Lt.smm[cnt]=Lt.val[cnt]=l; 144 Lt.mi[cnt]=Lt.tmp[cnt]=w;Lt.mipos[cnt]=cnt; 145 Lt.add(u,v,cnt); 146 break; 147 } 148 case 'm':{ 149 u=read()+1;v=read()+1; 150 int res=Lt.query(u,v); 151 printf("%d ",res); 152 break; 153 } 154 case 'c':{ 155 u=read();l=read(); 156 Lt.change(e[u].m,l); 157 break; 158 } 159 } 160 } 161 return 0; 162 }