Description
You are given an undirected graph with N vertexes and M edges. Every vertex in this graph has an integer value assigned to it at the beginning. You're also given a sequence of operations and you need to process them as requested. Here's a list of the possible operations that you might encounter:1) Deletes an edge from the graph.
The format is [D X], where X is an integer from 1 to M, indicating the ID of the edge that you should delete. It is guaranteed that no edge will be deleted more than once.
2) Queries the weight of the vertex with K-th maximum value among all vertexes currently connected with vertex X (including X itself).
The format is [Q X K], where X is an integer from 1 to N, indicating the id of the vertex, and you may assume that K will always fit into a 32-bit signed integer. In case K is illegal, the value for that query will be considered as undefined, and you should return 0 as the answer to that query.
3) Changes the weight of a vertex.
The format is [C X V], where X is an integer from 1 to N, and V is an integer within the range [-10 6, 10 6].
The operations end with one single character, E, which indicates that the current case has ended.
For simplicity, you only need to output one real number - the average answer of all queries.
Input
There are multiple test cases in the input file. Each case starts with two integers N and M (1 <= N <= 2 * 10 4, 0 <= M <= 6 * 10 4), the number of vertexes in the graph. The next N lines describes the initial weight of each vertex (-106 <= weight[i] <= 10 6). The next part of each test case describes the edges in the graph at the beginning. Vertexes are numbered from 1 to N. The last part of each test case describes the operations to be performed on the graph. It is guaranteed that the number of query operations [Q X K] in each case will be in the range [1, 2 * 10 5], and there will be no more than 2 * 10 5 operations that change the values of the vertexes [C X V].There will be a blank line between two successive cases. A case with N = 0, M = 0 indicates the end of the input file and this case should not be processed by your program.
Output
For each test case, output one real number � the average answer of all queries, in the format as indicated in the sample output. Please note that the result is rounded to six decimal places.Sample Input
3 3 10 20 30 1 2 2 3 1 3 D 3 Q 1 2 Q 2 1 D 2 Q 3 2 C 1 50 Q 1 1 E 3 3 10 20 20 1 2 2 3 1 3 Q 1 1 Q 1 2 Q 1 3 E 0 0Sample Output
Case 1: 25.000000 Case 2: 16.666667Hint
For the first sample: D 3 -- deletes the 3rd edge in the graph (the remaining edges are (1, 2) and (2, 3)) Q 1 2 -- finds the vertex with the second largest value among all vertexes connected with 1. The answer is 20. Q 2 1 -- finds the vertex with the largest value among all vertexes connected with 2. The answer is 30. D 2 -- deletes the 2nd edge in the graph (the only edge left after this operation is (1, 2)) Q 3 2 -- finds the vertex with the second largest value among all vertexes connected with 3. The answer is 0 (Undefined). C 1 50 -- changes the value of vertex 1 to 50. Q 1 1 -- finds the vertex with the largest value among all vertex connected with 1. The answer is 50. E -- This is the end of the current test case. Four queries have been evaluated, and the answer to this case is (20 + 30 + 0 + 50) / 4 = 25.000. For the second sample, caution about the vertex with same weight: Q 1 1 � the answer is 20 Q 1 2 � the answer is 20 Q 1 3 � the answer is 10
这题题意挺简单的,就是一张图,每个点有权值,然后三种操作,删边,该权值,求和x连通的第k大权值
这题第一眼看就是倒过来,然后加边维护就好了,然而要维护第k大会比较难,一开始我以为合并有什么巧妙的办法,然而后来发现都是暴力合并的,其实想想也是,暴力把少的加到多的里面,效率最多也就是多个log。然后是此题的坑点也很多,细节方面一定要注意,每个点建一个树,那么根之间的传递是必须要注意的,可以用并查集或者在删点的时候算好父节点。求的第k大,但是k还有可能是负的。。。
没用并查集的
#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
#include<vector>
#include<iostream>
#include<algorithm>
#include<bitset>
#include<functional>
using namespace std;
typedef long long LL;
const int maxn = 5e5 + 10;
const int mod = 1e9 + 7;
int n, m, sz, x, tot, cas = 0;
int v[maxn], ft[maxn], nt[maxn], root[maxn];
char s[5];
void add(int x, int y)
{
v[sz] = y; nt[sz] = ft[x]; ft[x] = sz++;
}
struct point
{
int x, y, z;
void read(){ scanf("%d%d", &x, &y); }
}p[maxn], q[maxn];
struct Splays
{
const static int maxn = 5e5 + 10; //节点个数
const static int INF = 0x7FFFFFFF; //int最大值
int ch[maxn][2], F[maxn], sz; //左右儿子,父亲节点和节点总个数
int A[maxn], C[maxn], S[maxn], now;
int Node(int f, int a, int s) { S[sz] = C[sz] = s; A[sz] = a; ch[sz][0] = ch[sz][1] = 0; F[sz] = f; return sz++; }//申请一个新节点
void clear(){ sz = 1; ch[0][0] = ch[0][1] = F[0] = 0; S[0] = C[0] = 0; }//清空操作
void rotate(int x, int k)
{
int y = F[x]; ch[y][!k] = ch[x][k]; F[ch[x][k]] = y;
if (F[y]) ch[F[y]][y == ch[F[y]][1]] = x;
F[x] = F[y]; F[y] = x; ch[x][k] = y;
C[x] = C[y]; C[y] = C[ch[y][0]] + C[ch[y][1]] + S[y];
}
void Splay(int x, int r)
{
while (F[x] != r)
{
if (F[F[x]] == r) { rotate(x, x == ch[F[x]][0]); return; }
int y = x == ch[F[x]][0], z = F[x] == ch[F[F[x]]][0];
y^z ? (rotate(x, y), rotate(x, z)) : (rotate(F[x], z), rotate(x, y));
}
}
int build(int v){ return Node(0, v, 1); }
int find(int x,int k)
{
int fx = root[x];
while (F[fx]) fx = F[fx];
if (C[fx] < k||k<=0) return 0;
k = C[fx] + 1 - k;
for (int i = fx; i;)
{
if (C[ch[i][0]] >= k) { i = ch[i][0]; continue; }
if (C[ch[i][0]] + S[i] >= k) return A[i];
k -= C[ch[i][0]] + S[i]; i = ch[i][1];
}
}
void insert(int x)
{
ch[x][0] = ch[x][1] = 0; F[x] = now; C[x] = S[x];
for (int i = now; i; i = ch[i][A[x] > A[i]])
{
C[i] += S[x];
if (A[x] == A[i]) { S[i] += S[x]; Splay(i, 0); now = i; return; }
if (!ch[i][A[x] > A[i]]){ ch[i][A[x] > A[i]] = x; F[x] = i; Splay(x, 0); now = x; return; }
}
}
void dfs(int x)
{
if (!x) return;
dfs(ch[x][0]);
dfs(ch[x][1]);
insert(x);
}
void merge(int x, int y)
{
int fx = root[x], fy = root[y];
while (F[fx]) fx = F[fx];
while (F[fy]) fy = F[fy];
if (fx == fy) return;
if (C[fx] > C[fy]) swap(fx, fy);
now = fy; dfs(fx); root[x] = root[y] = now;
}
void change(int x, int y, int z)
{
int fx = root[x], zz = Node(0, z, 1);
while (F[fx]) fx = F[fx];
now = fx; insert(zz);
for (int i = now; i; i = ch[i][y > A[i]]) if (A[i] == y) { Splay(i, 0); now = i; break; }
if (S[now] > 1) { S[now]--, C[now]--; return; }
if (!ch[now][0] || !ch[now][1]){ F[now] = ch[now][0] + ch[now][1]; now = F[now]; F[now] = 0; root[x] = now; return; }
for (int i = ch[now][0]; i; i = ch[i][1]) if (!ch[i][1]) { Splay(i, 0); now = i; break; }
int temp = ch[now][1]; ch[now][1] = ch[temp][1]; F[ch[now][1]] = now; C[now]--; root[x] = now;
}
}solve;
int main()
{
while (scanf("%d%d", &n, &m) != EOF, n + m)
{
sz = 0; solve.clear();
for (int i = 1; i <= n; i++) scanf("%d", &x), ft[i] = -1, add(i, x);
for (int i = 1; i <= m; i++) p[i].read(), p[i].z = 1;
for (tot = 0; scanf("%s", s), s[0] != 'E'; tot++)
{
q[tot].z = s[0] == 'D' ? 0 : s[0] == 'Q' ? 1 : 2;
if (!q[tot].z)
{
scanf("%d", &q[tot].x);
p[q[tot].x].z = 0;
}
else
{
q[tot].read();
if (q[tot].z == 2) add(q[tot].x, q[tot].y);
}
}
for (int i = 1; i <= n; i++) root[i] = solve.build(v[ft[i]]);
for (int i = 1; i <= m; i++) if (p[i].z) solve.merge(p[i].x, p[i].y);
LL ans = 0, div = 0;
for (int i = tot - 1; i >= 0; i--)
{
if (!q[i].z) solve.merge(p[q[i].x].x, p[q[i].x].y);
else
{
if (q[i].z == 1) ans += solve.find(q[i].x, q[i].y), div++;
else
{
ft[q[i].x] = nt[ft[q[i].x]];
solve.change(q[i].x, q[i].y, v[ft[q[i].x]]);
}
}
}
printf("Case %d: %.6lf\n", ++cas, 1.0*ans / div);
}
return 0;
}
用并查集的
#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
#include<vector>
#include<iostream>
#include<algorithm>
#include<bitset>
#include<functional>
using namespace std;
typedef long long LL;
const int maxn = 5e5 + 10;
const int mod = 1e9 + 7;
int n, m, sz, x, tot, cas = 0;
int v[maxn], ft[maxn], nt[maxn], root[maxn], fa[maxn];
char s[10];
void add(int x, int y)
{
v[sz] = y; nt[sz] = ft[x]; ft[x] = sz++;
}
int get(int x)
{
return x == fa[x] ? x : fa[x] = get(fa[x]);
}
struct point
{
int x, y, z;
void read(){ scanf("%d%d", &x, &y); }
}p[maxn], q[maxn];
struct Splays
{
const static int maxn = 5e5 + 10; //节点个数
const static int INF = 0x7FFFFFFF; //int最大值
int ch[maxn][2], F[maxn], sz; //左右儿子,父亲节点和节点总个数
int A[maxn], C[maxn], S[maxn], now;
int Node(int f, int a, int s) { S[sz] = C[sz] = s; A[sz] = a; ch[sz][0] = ch[sz][1] = 0; F[sz] = f; return sz++; }//申请一个新节点
void clear(){ sz = 1; ch[0][0] = ch[0][1] = F[0] = 0; S[0] = C[0] = 0; }//清空操作
void rotate(int x, int k)
{
int y = F[x]; ch[y][!k] = ch[x][k]; F[ch[x][k]] = y;
if (F[y]) ch[F[y]][y == ch[F[y]][1]] = x;
F[x] = F[y]; F[y] = x; ch[x][k] = y;
C[x] = C[y]; C[y] = C[ch[y][0]] + C[ch[y][1]] + S[y];
}
void Splay(int x, int r)
{
while (F[x] != r)
{
if (F[F[x]] == r) { rotate(x, x == ch[F[x]][0]); return; }
int y = x == ch[F[x]][0], z = F[x] == ch[F[F[x]]][0];
y^z ? (rotate(x, y), rotate(x, z)) : (rotate(F[x], z), rotate(x, y));
}
}
int build(int v){ return Node(0, v, 1); }
int find(int x,int k)
{
int fx = get(x), rx = root[fx];
Splay(rx, 0);
if (C[rx] < k || k <= 0) return 0;
k = C[rx] + 1 - k;
for (int i = rx; i;)
{
if (C[ch[i][0]] >= k) { i = ch[i][0]; continue; }
if (C[ch[i][0]] + S[i] >= k) return A[i];
k -= C[ch[i][0]] + S[i]; i = ch[i][1];
}
}
void insert(int x)
{
F[x] = ch[x][0] = ch[x][1] = 0; C[x] = S[x];
for (int i = now; i; i = ch[i][A[x] > A[i]])
{
C[i] += S[x];
if (A[x] == A[i]) { S[i] += S[x]; Splay(i, 0); now = i; return; }
if (!ch[i][A[x] > A[i]]){ ch[i][A[x] > A[i]] = x; F[x] = i; Splay(x, 0); now = x; return; }
}
}
void dfs(int x)
{
if (!x) return;
dfs(ch[x][0]);
dfs(ch[x][1]);
insert(x);
}
void merge(int x, int y)
{
int fx = get(x), fy = get(y);
if (fx == fy) return;
int rx = root[fx], ry = root[fy];
Splay(rx, 0); Splay(ry, 0);
if (C[rx] > C[ry]) swap(rx, ry), swap(fx, fy);
fa[fx] = fy; now = ry; dfs(rx); root[fy] = now;
}
void change(int x, int y, int z)
{
int fx = get(x), rx = root[fx], zz = Node(0, z, 1);
Splay(rx, 0); now = rx; insert(zz);
for (int i = now; i; i = ch[i][y > A[i]]) if (A[i] == y) { Splay(i, 0); now = i; break; }
if (S[now] > 1) { S[now]--, C[now]--; return; }
if (!ch[now][0] || !ch[now][1]){ now = ch[now][0] + ch[now][1]; F[now] = 0; root[fx] = now; return; }
for (int i = ch[now][0]; i; i = ch[i][1]) if (!ch[i][1]) { Splay(i, 0); now = i; break; }
int temp = ch[now][1]; ch[now][1] = ch[temp][1]; F[ch[now][1]] = now; C[now]--; root[fx] = now;
}
}solve;
int main()
{
while (scanf("%d%d", &n, &m) != EOF, n + m)
{
sz = 0; solve.clear();
for (int i = 1; i <= n; i++) scanf("%d", &x), ft[i] = -1, add(i, x), fa[i] = i;
for (int i = 1; i <= m; i++) p[i].read(), p[i].z = 1;
for (tot = 0; scanf("%s", s), s[0] != 'E'; tot++)
{
q[tot].z = s[0] == 'D' ? 0 : s[0] == 'Q' ? 1 : 2;
if (!q[tot].z)
{
scanf("%d", &q[tot].x);
p[q[tot].x].z = 0;
}
else
{
q[tot].read();
if (q[tot].z == 2) add(q[tot].x, q[tot].y);
}
}
for (int i = 1; i <= n; i++) root[i] = solve.build(v[ft[i]]);
for (int i = 1; i <= m; i++) if (p[i].z) solve.merge(p[i].x, p[i].y);
double ans = 0;
int div = 0;
for (int i = tot - 1; i >= 0; i--)
{
if (!q[i].z) solve.merge(p[q[i].x].x, p[q[i].x].y);
else
{
if (q[i].z == 1) ans += solve.find(q[i].x, q[i].y), div++;
else
{
ft[q[i].x] = nt[ft[q[i].x]];
solve.change(q[i].x, q[i].y, v[ft[q[i].x]]);
}
}
}
printf("Case %d: %.6f\n", ++cas, ans / div);
}
return 0;
}
相同权值不合并版
#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
#include<vector>
#include<iostream>
#include<algorithm>
#include<bitset>
#include<functional>
using namespace std;
typedef long long LL;
const int maxn = 5e5 + 10;
const int mod = 1e9 + 7;
int n, m, sz, x, tot, cas = 0;
int v[maxn], ft[maxn], nt[maxn], root[maxn], fa[maxn];
char s[10];
void add(int x, int y)
{
v[sz] = y; nt[sz] = ft[x]; ft[x] = sz++;
}
int get(int x)
{
return x == fa[x] ? x : fa[x] = get(fa[x]);
}
struct point
{
int x, y, z;
void read(){ scanf("%d%d", &x, &y); }
}p[maxn], q[maxn];
struct Splays
{
const static int maxn = 5e5 + 10; //节点个数
const static int INF = 0x7FFFFFFF; //int最大值
int ch[maxn][2], F[maxn], sz; //左右儿子,父亲节点和节点总个数
int A[maxn], C[maxn], now;
int Node(int f, int a) { C[sz] = 1; A[sz] = a; ch[sz][0] = ch[sz][1] = 0; F[sz] = f; return sz++; }//申请一个新节点
void clear(){ sz = 1; ch[0][0] = ch[0][1] = F[0] = 0; C[0] = 0; }//清空操作
void rotate(int x, int k)
{
int y = F[x]; ch[y][!k] = ch[x][k]; F[ch[x][k]] = y;
if (F[y]) ch[F[y]][y == ch[F[y]][1]] = x;
F[x] = F[y]; F[y] = x; ch[x][k] = y;
C[x] = C[y]; C[y] = C[ch[y][0]] + C[ch[y][1]] + 1;
}
void Splay(int x, int r)
{
while (F[x] != r)
{
if (F[F[x]] == r) { rotate(x, x == ch[F[x]][0]); return; }
int y = x == ch[F[x]][0], z = F[x] == ch[F[F[x]]][0];
y^z ? (rotate(x, y), rotate(x, z)) : (rotate(F[x], z), rotate(x, y));
}
}
int build(int v){ return Node(0, v); }
int find(int x,int k)
{
int fx = get(x), rx = root[fx];
Splay(rx, 0);
if (C[rx] < k || k <= 0) return 0;
k = C[rx] + 1 - k;
for (int i = rx; i;)
{
if (C[ch[i][0]] >= k) { i = ch[i][0]; continue; }
if (C[ch[i][0]] + 1 >= k) return A[i];
k -= C[ch[i][0]] + 1; i = ch[i][1];
}
}
void insert(int x)
{
F[x] = ch[x][0] = ch[x][1] = 0; C[x] = 1;
for (int i = now; i; i = ch[i][A[x] > A[i]])
{
C[i] += 1;
if (!ch[i][A[x] > A[i]]){ ch[i][A[x] > A[i]] = x; F[x] = i; Splay(x, 0); now = x; return; }
}
}
void dfs(int x)
{
if (!x) return;
dfs(ch[x][0]);
dfs(ch[x][1]);
insert(x);
}
void merge(int x, int y)
{
int fx = get(x), fy = get(y);
if (fx == fy) return;
int rx = root[fx], ry = root[fy];
Splay(rx, 0); Splay(ry, 0);
if (C[rx] > C[ry]) swap(rx, ry), swap(fx, fy);
fa[fx] = fy; now = ry; dfs(rx); root[fy] = now;
}
void change(int x, int y, int z)
{
int fx = get(x), rx = root[fx], zz = Node(0, z);
Splay(rx, 0); now = rx; insert(zz);
for (int i = now; i; i = ch[i][y > A[i]]) if (A[i] == y) { Splay(i, 0); now = i; break; }
if (!ch[now][0] || !ch[now][1]){ now = ch[now][0] + ch[now][1]; F[now] = 0; root[fx] = now; return; }
for (int i = ch[now][0]; i; i = ch[i][1]) if (!ch[i][1]) { Splay(i, 0); now = i; break; }
int temp = ch[now][1]; ch[now][1] = ch[temp][1]; F[ch[now][1]] = now; C[now]--; root[fx] = now;
}
}solve;
int main()
{
while (scanf("%d%d", &n, &m) != EOF, n + m)
{
sz = 0; solve.clear();
for (int i = 1; i <= n; i++) scanf("%d", &x), ft[i] = -1, add(i, x), fa[i] = i;
for (int i = 1; i <= m; i++) p[i].read(), p[i].z = 1;
for (tot = 0; scanf("%s", s), s[0] != 'E'; tot++)
{
q[tot].z = s[0] == 'D' ? 0 : s[0] == 'Q' ? 1 : 2;
if (!q[tot].z)
{
scanf("%d", &q[tot].x);
p[q[tot].x].z = 0;
}
else
{
q[tot].read();
if (q[tot].z == 2) add(q[tot].x, q[tot].y);
}
}
for (int i = 1; i <= n; i++) root[i] = solve.build(v[ft[i]]);
for (int i = 1; i <= m; i++) if (p[i].z) solve.merge(p[i].x, p[i].y);
double ans = 0;
int div = 0;
for (int i = tot - 1; i >= 0; i--)
{
if (!q[i].z) solve.merge(p[q[i].x].x, p[q[i].x].y);
else
{
if (q[i].z == 1) ans += solve.find(q[i].x, q[i].y), div++;
else
{
ft[q[i].x] = nt[ft[q[i].x]];
solve.change(q[i].x, q[i].y, v[ft[q[i].x]]);
}
}
}
printf("Case %d: %.6f\n", ++cas, ans / div);
}
return 0;
}
标签:sz,HDU,ch,int,Graph,fx,maxn,3726,now From: https://blog.51cto.com/u_15870896/5838870