Problem

给你一张图,点的权值,边和几个操作:

D x: 删除第x条边

Q x y: 询问包含x的联通块中权值第y大的权值

C x y: 将x这个点的权值改为y

Solution

一看就要离线处理,把所有操作都倒过来

然后删除操作变为加边操作

Notice

记得: 是改完以后再把点一个一个加入Treap中!!

Code

非旋转Treap

#pragma GCC optimize(2)
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define sqz main
#define ll long long
#define reg register int
#define rep(i, a, b) for (reg i = a; i <= b; i++)
#define per(i, a, b) for (reg i = a; i >= b; i--)
#define travel(i, u) for (reg i = head[u]; i; i = edge[i].next)
const int INF = 1e9, N = 3000000;
const double eps = 1e-6, phi = acos(-1.0);
ll mod(ll a, ll b) {if (a >= b || a < 0) a %= b; if (a < 0) a += b; return a;}
ll read(){ ll x = 0; int zf = 1; char ch; while (ch != '-' && (ch < '0' || ch > '9')) ch = getchar();
if (ch == '-') zf = -1, ch = getchar(); while (ch >= '0' && ch <= '9') x = x * 10 + ch - '0', ch = getchar(); return x * zf;}
void write(ll y) { if (y < 0) putchar('-'), y = -y; if (y > 9) write(y / 10); putchar(y % 10 + '0');}
struct Node
{
int num1, num2, type;
}Q[N + 5];
int point = 0, fa[N + 5], Root[N + 5], T[N + 5], From[N + 5], To[N + 5], Flag[N + 5];
struct node
{
int Val[N + 5], Level[N + 5], Size[N + 5], Son[2][N + 5], Num[N + 5];
inline void up(int u)
{
Size[u] = Size[Son[0][u]] + Size[Son[1][u]] + 1;
}
int Newnode(int v)
{
int u = ++point;
Val[u] = v, Level[u] = rand();
Son[0][u] = Son[1][u] = 0, Size[u] = 1;
return u;
}
int Merge(int X, int Y)
{
if (X * Y == 0) return X + Y;
if (Level[X] < Level[Y])
{
Son[1][X] = Merge(Son[1][X], Y);
up(X); return X;
}
else
{
Son[0][Y] = Merge(X, Son[0][Y]);
up(Y); return Y;
}
}
void Split(int u, int t, int &x, int &y)
{
if (!u)
{
x = y = 0;
return;
}
if (Val[u] <= t) x = u, Split(Son[1][u], t, Son[1][u], y);
else y = u, Split(Son[0][u], t, x, Son[0][u]);
up(u);
}
int Find_num(int u, int v)
{
if (!u) return 0;
if (v <= Size[Son[0][u]]) return Find_num(Son[0][u], v);
else if (v <= Size[Son[0][u]] + 1) return u;
else return Find_num(Son[1][u], v - Size[Son[0][u]] - 1);
}
void Insert(int &u, int v)
{
int t = Newnode(v), x, y;
Split(u, v, x, y);
u = Merge(Merge(x, t), y);
}
void Delete(int &u, int v)
{
int x, y, z;
Split(u, v, x, z), Split(x, v - 1, x, y);
u = Merge(Merge(x, Merge(Son[0][y], Son[1][y])), z);
}
}Treap;
int Find(int x)
{
if (fa[x] != x) fa[x] = Find(fa[x]);
return fa[x];
}
void Union(int u, int v)
{
if (Treap.Size[Root[u]] < Treap.Size[Root[v]]) swap(u, v);
while (Treap.Size[Root[v]])
{
int t = Treap.Find_num(Root[v], 1);
Treap.Insert(Root[u], Treap.Val[t]);
Treap.Delete(Root[v], Treap.Val[t]);
}
fa[v] = u;
Root[v] = 0;
}
int sqz()
{
int n, m, cas = 0;
while (~scanf("%d %d", &n, &m) && (n || m))
{
point = 0;
rep(i, 1, n) T[i] = read(), fa[i] = i, Root[i] = 0;
rep(i, 1, m) From[i] = read(), To[i] = read(), Flag[i] = 0;
int q = 0; char op[5];
while (scanf("%s", op) && op[0] != 'E')
{
q++;
if (op[0] == 'D')
Q[q].num1 = read(), Flag[Q[q].num1] = 1, Q[q].type = 0;
else
{
Q[q].num1 = read(), Q[q].num2 = read();
if (op[0] == 'C') swap(T[Q[q].num1], Q[q].num2), Q[q].type = 1;
else Q[q].type = 2;
}
}
rep(i, 1, n) Treap.Insert(Root[i], T[i]);
rep(i, 1, m)
if (!Flag[i])
{
int u = Find(From[i]), v = Find(To[i]);
if (u != v) Union(u, v);
}
ll ans = 0; int tot = 0;
per(i, q, 1)
{
if (Q[i].type == 0)
{
int u = Find(From[Q[i].num1]), v = Find(To[Q[i].num1]);
if (u != v) Union(u, v);
}
else if (Q[i].type == 1)
{
int u = Find(Q[i].num1);
Treap.Delete(Root[u], T[Q[i].num1]);
Treap.Insert(Root[u], Q[i].num2);
T[Q[i].num1] = Q[i].num2;
}
else
{
int u = Find(Q[i].num1);
int t = Treap.Find_num(Root[u], Treap.Size[Root[u]] - Q[i].num2 + 1);
if (t != -INF) ans += Treap.Val[t];
tot++;
}
}
printf("Case %d: %.6f\n", ++cas, ans * 1.0 / tot);
}
return 0;
}

旋转Treap

#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define sqz main
#define ll long long
#define reg register int
#define rep(i, a, b) for (reg i = a; i <= b; i++)
#define per(i, a, b) for (reg i = a; i >= b; i--)
#define travel(i, u) for (reg i = head[u]; i; i = edge[i].next)
const int INF = 1e9, N = 3000000;
const double eps = 1e-6, phi = acos(-1.0);
ll mod(ll a, ll b) {if (a >= b || a < 0) a %= b; if (a < 0) a += b; return a;}
ll read(){ ll x = 0; int zf = 1; char ch; while (ch != '-' && (ch < '0' || ch > '9')) ch = getchar();
if (ch == '-') zf = -1, ch = getchar(); while (ch >= '0' && ch <= '9') x = x * 10 + ch - '0', ch = getchar(); return x * zf;}
void write(ll y) { if (y < 0) putchar('-'), y = -y; if (y > 9) write(y / 10); putchar(y % 10 + '0');}
struct Node
{
int num1, num2, type;
}Q[N + 5];
int point = 0, fa[N + 5], Root[N + 5], T[N + 5], From[N + 5], To[N + 5], Flag[N + 5];
struct node
{
int Val[N + 5], Level[N + 5], Size[N + 5], Son[2][N + 5], Num[N + 5];
inline void up(int u)
{
Size[u] = Size[Son[0][u]] + Size[Son[1][u]] + Num[u];
}
inline void Newnode(int &u, int v)
{
u = ++point;
Level[u] = rand(), Val[u] = v;
Size[u] = Num[u] = 1, Son[0][u] = Son[1][u] = 0;
}
inline void Lturn(int &x)
{
int y = Son[1][x]; Son[1][x] = Son[0][y], Son[0][y] = x;
up(x); up(y); x = y;
}
inline void Rturn(int &x)
{
int y = Son[0][x]; Son[0][x] = Son[1][y], Son[1][y] = x;
up(x); up(y); x = y;
} void Insert(int &u, int t)
{
if (u == 0)
{
Newnode(u, t);
return;
}
Size[u]++;
if (t == Val[u]) Num[u]++;
else if (t > Val[u])
{
Insert(Son[0][u], t);
if (Level[Son[0][u]] < Level[u]) Rturn(u);
}
else if (t < Val[u])
{
Insert(Son[1][u], t);
if (Level[Son[1][u]] < Level[u]) Lturn(u);
}
}
void Delete(int &u, int t)
{
if (!u) return;
if (Val[u] == t)
{
if (Num[u] > 1)
{
Num[u]--, Size[u]--;
return;
}
if (Son[0][u] * Son[1][u] == 0) u = Son[0][u] + Son[1][u];
else if (Level[Son[0][u]] < Level[Son[1][u]]) Rturn(u), Delete(u, t);
else Lturn(u), Delete(u, t);
}
else if (t > Val[u]) Size[u]--, Delete(Son[0][u], t);
else Size[u]--, Delete(Son[1][u], t);
} int Find_num(int u, int t)
{
if (!u) return -INF;
if (t <= Size[Son[0][u]]) return Find_num(Son[0][u], t);
else if (t <= Size[Son[0][u]] + Num[u]) return Val[u];
else return Find_num(Son[1][u], t - Size[Son[0][u]] - Num[u]);
}
}Treap;
int Find(int x)
{
if (fa[x] != x) fa[x] = Find(fa[x]);
return fa[x];
}
void Union(int u, int v)
{
if (Treap.Size[Root[u]] < Treap.Size[Root[v]]) swap(u, v);
while (Treap.Size[Root[v]])
{
int t = Treap.Find_num(Root[v], 1);
Treap.Insert(Root[u], t);
Treap.Delete(Root[v], t);
}
fa[v] = u;
Root[v] = 0;
}
int sqz()
{
int n, m, cas = 0;
while (~scanf("%d %d", &n, &m) && (n || m))
{
point = 0;
rep(i, 1, n) T[i] = read(), fa[i] = i, Root[i] = 0;
rep(i, 1, m) From[i] = read(), To[i] = read(), Flag[i] = 0;
int q = 0; char op[5];
while (scanf("%s", op) && op[0] != 'E')
{
q++;
if (op[0] == 'D')
Q[q].num1 = read(), Flag[Q[q].num1] = 1, Q[q].type = 0;
else
{
Q[q].num1 = read(), Q[q].num2 = read();
if (op[0] == 'C') swap(T[Q[q].num1], Q[q].num2), Q[q].type = 1;
else Q[q].type = 2;
}
}
rep(i, 1, n) Treap.Insert(Root[i], T[i]);
rep(i, 1, m)
if (!Flag[i])
{
int u = Find(From[i]), v = Find(To[i]);
if (u != v) Union(u, v);
}
ll ans = 0; int tot = 0;
per(i, q, 1)
{
if (Q[i].type == 0)
{
int u = Find(From[Q[i].num1]), v = Find(To[Q[i].num1]);
if (u != v) Union(u, v);
}
else if (Q[i].type == 1)
{
int u = Find(Q[i].num1);
Treap.Delete(Root[u], T[Q[i].num1]);
Treap.Insert(Root[u], Q[i].num2);
T[Q[i].num1] = Q[i].num2;
}
else
{
int u = Find(Q[i].num1);
int t = Treap.Find_num(Root[u], Q[i].num2);
if (t != -INF) ans += t;
tot++;
}
}
printf("Case %d: %.6f\n", ++cas, ans * 1.0 / tot);
}
return 0;
}

[HDU3726]Graph and Queries的更多相关文章

  1. HDU 3726 Graph and Queries 平衡树+前向星+并查集+离线操作+逆向思维 数据结构大综合题

    Graph and Queries Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Other ...

  2. HDU 3726 Graph and Queries (离线处理+splay tree)

    Graph and Queries Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Other ...

  3. [la P5031&hdu P3726] Graph and Queries

    [la P5031&hdu P3726] Graph and Queries Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: ...

  4. HDU 3726 Graph and Queries treap树

    题目来源:HDU 3726 Graph and Queries 题意:见白书 思路:刚学treap 參考白皮书 #include <cstdio> #include <cstring ...

  5. HDU 3726 Graph and Queries(平衡二叉树)(2010 Asia Tianjin Regional Contest)

    Description You are given an undirected graph with N vertexes and M edges. Every vertex in this grap ...

  6. UVALive5031 Graph and Queries(Treap)

    反向操作,先求出最终状态,再反向操作. 然后就是Treap 的合并,求第K大值. #include<cstdio> #include<iostream> #include< ...

  7. UVa 1479 (Treap 名次树) Graph and Queries

    这题写起来真累.. 名次树就是多了一个附加信息记录以该节点为根的树的总结点的个数,由于BST的性质再根据这个附加信息,我们可以很容易找到这棵树中第k大的值是多少. 所以在这道题中用一棵名次树来维护一个 ...

  8. uvalive 5031 Graph and Queries 名次树+Treap

    题意:给你个点m条边的无向图,每个节点都有一个整数权值.你的任务是执行一系列操作.操作分为3种... 思路:本题一点要逆向来做,正向每次如果删边,复杂度太高.逆向到一定顺序的时候添加一条边更容易.详见 ...

  9. 【HDOJ】3726 Graph and Queries

    Treap的基础题目,Treap是个挺不错的数据结构. /* */ #include <iostream> #include <string> #include <map ...

随机推荐

  1. 查询选修了全部课程的学生姓名_如何解?-MS-SQLServer/应用实例

    查询选修了全部课程的学生姓名:student 是学生表 course 是选课表 sc 是课程表select snamefrom studentwhere not exists(select *from ...

  2. 初探nginx负载均衡配置

    只简单说一下upstream的配置,如何进行负载均衡后续还需要多了解 1.另准备一个配置文件命名为nginx_test.conf 为了不污染原有的nginx.conf,提前复制一份配置文件做试验,然后 ...

  3. PHP数组合并和去重的函数有哪些

    PHP数组合并和去重的函数有哪些 一.总结 一句话总结:合并:array_merge() array_merge_recursive() +号:去重:array_flip() array_unique ...

  4. c++-pimer-plus-6th-chapter06

    Chapter Review 1 Both version give the same answers, but the if else version is more efficient. Cons ...

  5. 20170914xlVBA通讯公司分类汇总

    Sub 租房() Dim Wb As Workbook Dim Sht As Worksheet Dim OpenWb As Workbook Dim OpenSht As Worksheet Dim ...

  6. 数组方法map(映射),reduce(规约),foreach(遍历),filter(过滤)

    数组方法map(映射),reduce(规约),foreach(遍历),filter(过滤) map()方法返回一个由原数组中每一个元素调用一个指定方法后返回的新数组 reduce()方法接受一个函数作 ...

  7. 『计算机视觉』Mask-RCNN

    一.Mask-RCNN流程 Mask R-CNN是一个实例分割(Instance segmentation)算法,通过增加不同的分支,可以完成目标分类.目标检测.语义分割.实例分割.人体姿势识别等多种 ...

  8. web中集成shiro

    Shiro提供了与Web集成的支持,其通过一个ShiroFilter入口来拦截需要安全控制的URL,然后进行相应的控制,ShiroFilter类似于如Strut2/SpringMVC这种web框架的前 ...

  9. Django之转发和重定向

    https://blog.csdn.net/gscsd_t/article/details/79389167 转发和重定向: 转发:一次请求和响应,请求的地址没有发生变化,如果此时刷新页面,就会出现重 ...

  10. leetcode_输入一个数组,目标树,检查目标是数组下标的哪两个之和,不准重复

    今天是leetcode第一天,但是不太顺利.做这些,想不到 原题目: 我给的答案: class Solution { public: vector<int> twoSum(vector&l ...