1 #include<cstdio> 2 #include<iostream> 3 #define MAXN 400010 4 #define PushUp(x) num[x] = num[next[x][0]] + num[next[x][1]] + 1; 5 using namespace std; 6 pair<int, int> edge[MAXN]; 7 int first[MAXN], next[MAXN], cost[MAXN], e; 8 int father[MAXN]; 9 bool del[MAXN]; 10 struct ASK { 11 char cmd; 12 int x, k; 13 } a[MAXN]; 14 struct SplayTree { 15 int root; 16 int next[MAXN][2], pre[MAXN], key[MAXN], num[MAXN]; 17 void Init() { 18 root = next[0][0] = next[0][1] = pre[0] = num[0] = key[0] = 0; 19 } 20 inline void NewNode(int &x, int loc, int father, int val) { 21 x = loc; 22 next[x][0] = next[x][1] = 0; 23 pre[x] = father; 24 key[x] = val; 25 num[x] = 1; 26 } 27 inline void Rotate(int x, int kind) { 28 int y, z; 29 y = pre[x]; 30 z = pre[y]; 31 next[y][!kind] = next[x][kind]; 32 pre[next[x][kind]] = y; 33 next[z][next[z][1] == y] = x; 34 pre[x] = z; 35 next[x][kind] = y; 36 pre[y] = x; 37 PushUp(y); 38 } 39 void Splay(int x, int goal) { 40 if (x != goal) { 41 while (pre[x] != goal) { 42 if (next[pre[x]][0] == x) 43 Rotate(x, 1); 44 else 45 Rotate(x, 0); 46 } 47 PushUp(x); 48 if (!goal) 49 root = x; 50 } 51 } 52 int Select(int x, int k) { 53 k = num[x] - k + 1; 54 while (num[next[x][0]] + 1 != k) { 55 if (num[next[x][0]] + 1 > k) 56 x = next[x][0]; 57 else { 58 k -= num[next[x][0]] + 1; 59 x = next[x][1]; 60 } 61 } 62 Splay(x, 0); 63 return x; 64 } 65 void Insert(int x, int y, int val) { 66 while (next[y][val > key[y]]) 67 y = next[y][val > key[y]]; 68 NewNode(next[y][val > key[y]], x, y, val); 69 } 70 void DFS(int x) { 71 if (x) { 72 DFS(next[x][0]); 73 DFS(next[x][1]); 74 Insert(x, root, key[x]); 75 Splay(x, 0); 76 } 77 } 78 void Join(int x, int y) { 79 Splay(x, 0); 80 Splay(y, 0); 81 if (num[x] > num[y]) 82 swap(x, y); 83 root = y; 84 DFS(x); 85 } 86 int Query(int x, int k) { 87 if (k < 1) 88 return 0; 89 Splay(x, 0); 90 if (num[x] < k) 91 return 0; 92 return key[Select(x, k)]; 93 } 94 void Change(int x, int val) { 95 int a, b; 96 Splay(x, 0); 97 a = next[x][0]; 98 b = next[x][1]; 99 pre[a] = pre[b] = 0; 100 if (a && b) { 101 while (next[b][0]) 102 b = next[b][0]; 103 next[b][0] = a; 104 pre[a] = b; 105 Splay(a, 0); 106 Insert(x, a, val); 107 } else if (a) 108 Insert(x, a, val); 109 else if (b) 110 Insert(x, b, val); 111 else 112 key[x] = val; 113 Splay(x, 0); 114 } 115 } spt; 116 int INT() { 117 bool neg; 118 int res; 119 char ch; 120 while (ch = getchar(), !isdigit(ch) && ch != '-') 121 ; 122 if (ch == '-') { 123 neg = true; 124 res = 0; 125 } else { 126 neg = false; 127 res = ch - '0'; 128 } 129 for (; ch = getchar(), isdigit(ch);) 130 res = res * 10 + ch - '0'; 131 return neg ? -res : res; 132 } 133 char CHAR() { 134 char ch; 135 while (ch = getchar(), !isalpha(ch)) 136 ; 137 return ch; 138 } 139 int FindSet(int x) { 140 if (x != father[x]) 141 father[x] = FindSet(father[x]); 142 return father[x]; 143 } 144 inline void AddEdge(int x, int val) { 145 cost[e] = val; 146 next[e] = first[x]; 147 first[x] = e++; 148 } 149 int main() { 150 int ca = 1; 151 double ans; 152 int n, m, q, i, cnt; 153 int x, y; 154 while (true) { 155 n = INT(), m = INT(); 156 if (!n && !m) 157 break; 158 spt.Init(); 159 for (e = 0, i = 1; i <= n; i++) { 160 father[i] = i; 161 first[i] = -1; 162 AddEdge(i, INT()); 163 } 164 for (i = 1; i <= m; i++) { 165 edge[i] = make_pair(INT(), INT()); 166 del[i] = false; 167 } 168 for (q = 0;; q++) { 169 a[q].cmd = CHAR(); 170 if (a[q].cmd == 'E') 171 break; 172 a[q].x = INT(); 173 if (a[q].cmd == 'D') 174 del[a[q].x] = true; 175 else { 176 a[q].k = INT(); 177 if (a[q].cmd == 'C') 178 AddEdge(a[q].x, a[q].k); 179 } 180 } 181 for (i = 1; i <= n; i++) { 182 spt.NewNode(spt.root, i, 0, cost[first[i]]); 183 first[i] = next[first[i]]; 184 } 185 for (i = 1; i <= m; i++) { 186 if (!del[i]) { 187 x = FindSet(edge[i].first); 188 y = FindSet(edge[i].second); 189 if (x != y) { 190 spt.Join(edge[i].first, edge[i].second); 191 father[x] = y; 192 } 193 } 194 } 195 ans = cnt = 0; 196 for (i = q - 1; i >= 0; i--) { 197 if (a[i].cmd == 'Q') { 198 cnt++; 199 ans += spt.Query(a[i].x, a[i].k); 200 } else if (a[i].cmd == 'D') { 201 x = FindSet(edge[a[i].x].first); 202 y = FindSet(edge[a[i].x].second); 203 if (x != y) { 204 spt.Join(edge[a[i].x].first, edge[a[i].x].second); 205 father[x] = y; 206 } 207 } else { 208 spt.Change(a[i].x, cost[first[a[i].x]]); 209 first[a[i].x] = next[first[a[i].x]]; 210 } 211 } 212 printf("Case %d: %lf\n", ca++, ans / cnt); 213 } 214 return 0; 215 }