【题目大意】

维护一个$n$个点的图,$m$个操作,支持两个操作:

1. 连接$(u, v)$这条边;

2. 询问$u$所在的联通块中,能选出的最大合法的点数。

一个方案是合法的,当且仅当对于所有被选择的点,他们都没有直接通过一条边相连。

$n \leq 2*10^5, m\leq 8*10^5$

【题解】

考虑用LCT来维护这个图。

对于实边的Splay,维护$h_it_j$,其中$i, j \in \{0, 1\}$,表示前面选择$i$,后面选择$j$。(选0表示不选,选1表示选)

这个是可以合并信息的。

考虑虚边,对于每个虚边连到的实边的点,维护$l_i$,其中$i \in \{0,1\}$,分别表示$l_i$必须为0,以及$l_i$可以为0的值。

那么$l_i$可以通过连的虚边的值转移来。

那么连到的实边的点的val就可以用$l_i$表示。

在access的时候和link的时候(link可以用两个makeroot来做)支持实边虚边转换即可。

# include <stdio.h>
# include <assert.h>
# include <iostream>
# include <string.h>
# include <algorithm> using namespace std; typedef long long ll;
typedef unsigned long long ull;
typedef long double ld; inline int getint() {
int x = ; char ch = getchar();
while(!isdigit(ch)) ch = getchar();
while(isdigit(ch)) x = (x<<) + (x<<) + ch - '', ch = getchar();
return x;
} const int N = 2e5 + , M = 5e5 + , inf = 1e9; int n, m; struct node {
int h0t0, h0t1, h1t0, h1t1;
node () {}
node (int h0t0, int h0t1, int h1t0, int h1t1) : h0t0(h0t0), h0t1(h0t1), h1t0(h1t0), h1t1(h1t1) {}
inline friend node operator + (node a, node b) {
// a tail with b head
node p;
p.h0t0 = max(a.h0t1 + b.h0t0, a.h0t0 + max(b.h1t0, b.h0t0));
p.h0t1 = max(a.h0t1 + b.h0t1, a.h0t0 + max(b.h1t1, b.h0t1));
p.h1t0 = max(a.h1t1 + b.h0t0, a.h1t0 + max(b.h1t0, b.h0t0));
p.h1t1 = max(a.h1t1 + b.h0t1, a.h1t0 + max(b.h1t1, b.h0t1));
return p;
}
inline int gans() {
return max(max(h0t0, h0t1), max(h1t0, h1t1));
}
inline void prt() {
printf("{%d %d %d %d}", h0t0, h0t1 == -inf ? - : h0t1, h1t0 == -inf ? - : h1t0, h1t1);
}
}; struct LCT {
node p[N], val[N]; int l0[N], l1[N];
int ch[N][], fa[N];
bool rev[N]; # define ls ch[x][]
# define rs ch[x][] inline void up(int x) {
if(!x) return ;
// ...
p[x] = val[x];
if(ls) p[x] = p[ls] + p[x];
if(rs) p[x] = p[x] + p[rs];
} inline void pushrev(int x) {
if(!x) return ;
swap(ch[x][], ch[x][]);
// ...
swap(p[x].h1t0, p[x].h0t1);
rev[x] ^= ;
} inline void down(int x) {
if(!x) return ;
if(rev[x]) {
pushrev(ls);
pushrev(rs);
rev[x] ^= ;
}
} # undef ls
# undef rs inline bool isrt(int x) {
return ch[fa[x]][] != x && ch[fa[x]][] != x;
} inline void rotate(int x) {
int y = fa[x], z = fa[y], ls = ch[y][] == x, rs = ls ^ ;
if(!isrt(y)) ch[z][ch[z][] == y] = x;
fa[ch[x][rs]] = y, fa[y] = x, fa[x] = z;
ch[y][ls] = ch[x][rs]; ch[x][rs] = y;
up(y); up(x);
} int st[N];
inline void splay(int x) {
int stn = , tx = x;
while(!isrt(tx)) st[++stn] = tx, tx = fa[tx];
st[++stn] = tx;
for (int i=stn; i; --i) down(st[i]);
while(!isrt(x)) {
int y = fa[x], z = fa[y];
if(!isrt(y)) {
if((ch[z][] == y) ^ (ch[y][] == x)) rotate(x);
else rotate(y);
}
rotate(x);
}
} inline void del(int y, int x) {
int p0 = max(p[x].h0t0, p[x].h0t1), p1 = max(p[x].h1t0, p[x].h1t1);
l0[y] += p0;
l1[y] += max(p0, p1);
}
inline void ins(int y, int x) {
int p0 = max(p[x].h0t0, p[x].h0t1), p1 = max(p[x].h1t0, p[x].h1t1);
l0[y] -= p0;
l1[y] -= max(p0, p1);
} inline int access(int x) {
int t = ;
for (; x; t = x, x = fa[x]) {
splay(x);
// ...
if(ch[x][]) del(x, ch[x][]);
if(t) ins(x, t);
val[x].h0t0 = l1[x];
val[x].h1t1 = l0[x] + ;
ch[x][] = t;
up(x);
}
return t;
} inline void makeroot(int x) {
access(x); splay(x); pushrev(x);
} inline void link(int x, int y) {
makeroot(x); makeroot(y);
fa[x] = y;
// ...
int p0 = max(p[x].h0t0, p[x].h0t1), p1 = max(p[x].h1t0, p[x].h1t1);
l0[y] += p0;
l1[y] += max(p0, p1);
val[y].h0t0 = l1[y];
val[y].h1t1 = l0[y] + ;
up(y);
} inline void debug() {
for (int x=; x<=n; ++x) {
printf("x = %d,fa = %d,ls = %d,rs = %d, p = ", x, fa[x], ch[x][], ch[x][]);
p[x].prt();
printf(", val = ");
val[x].prt();
printf(", l0 = %d,l1 = %d\n", l0[x], l1[x]);
}
}
}T; int main() {
freopen("game.in", "r", stdin);
freopen("game.out", "w", stdout);
n = getint();
for (int x=; x<=n; ++x) {
T.val[x] = T.p[x] = node(, -inf, -inf, );
T.ch[x][] = T.ch[x][] = T.fa[x] = ; T.rev[x] = ;
T.l0[x] = T.l1[x] = ;
}
register int Q = getint(), op, u, v;
while(Q--) {
// T.debug();
op = getint(), u = getint();
if(op == ) {
T.makeroot(u);
printf("%d\n", T.p[u].gans());
// cout << ... << endl;
} else {
v = getint();
T.link(u, v);
}
}
return ;
}

省队集训 Day7 选点游戏的更多相关文章

  1. HN2018省队集训

    HN2018省队集训 Day1 今天的题目来自于雅礼的高二学长\(dy0607\). 压缩包下载 密码: 27n7 流水账 震惊!穿着该校校服竟然在四大名校畅通无阻?霸主地位已定? \(7:10\)从 ...

  2. JS省队集训记

    不知不觉省队集训已经结束,离noi也越来越近了呢 论考前实战训练的重要性,让我随便总结一下这几天的考试 Day 1 T1 唉,感觉跟xj测试很像啊?meet in middle,不过这种题不多测是什么 ...

  3. 「2017 山东三轮集训 Day7 解题报告

    「2017 山东三轮集训 Day7」Easy 练习一下动态点分 每个点开一个线段树维护子树到它的距离 然后随便查询一下就可以了 注意线段树开大点... Code: #include <cstdi ...

  4. [2018HN省队集训D9T1] circle

    [2018HN省队集训D9T1] circle 题意 给定一个 \(n\) 个点的竞赛图并在其中钦定了 \(k\) 个点, 数据保证删去钦定的 \(k\) 个点后这个图没有环. 问在不删去钦定的这 \ ...

  5. 【LOJ6077】「2017 山东一轮集训 Day7」逆序对 生成函数+组合数+DP

    [LOJ6077]「2017 山东一轮集训 Day7」逆序对 题目描述 给定 n,k ,请求出长度为 n的逆序对数恰好为 k 的排列的个数.答案对 109+7 取模. 对于一个长度为 n 的排列 p ...

  6. [2018HN省队集训D8T1] 杀毒软件

    [2018HN省队集训D8T1] 杀毒软件 题意 给定一个 \(m\) 个01串的字典以及一个长度为 \(n\) 的 01? 序列. 对这个序列进行 \(q\) 次操作, 修改某个位置的字符情况以及查 ...

  7. [2018HN省队集训D8T3] 水果拼盘

    [2018HN省队集训D8T3] 水果拼盘 题意 给定 \(n\) 个集合, 每个集合包含 \([1,m]\) 中的一些整数, 在这些集合中随机选取 \(k\) 个集合, 求这 \(k\) 个集合的并 ...

  8. [2018HN省队集训D6T2] girls

    [2018HN省队集训D6T2] girls 题意 给定一张 \(n\) 个点 \(m\) 条边的无向图, 求选三个不同结点并使它们两两不邻接的所有方案的权值和 \(\bmod 2^{64}\) 的值 ...

  9. [Luogu P4143] 采集矿石 [2018HN省队集训D5T3] 望乡台platform

    [Luogu P4143] 采集矿石 [2018HN省队集训D5T3] 望乡台platform 题意 给定一个小写字母构成的字符串, 每个字符有一个非负权值. 输出所有满足权值和等于这个子串在所有本质 ...

随机推荐

  1. Java数组课程作业

    设计思路:生成随机数,赋值给数组.再将其求和输出 程序流程图: 源程序代码: import javax.swing.JOptionPane; public class Test { public st ...

  2. Android 上实现非root的 Traceroute -- 非Root权限下移植可执行二进制文件 脚本文件

    作者 : 万境绝尘 转载请著名出处 : http://blog.csdn.net/shulianghan/article/details/36438365 示例代码下载 : -- CSDN : htt ...

  3. P4语法(1)基础数据类型和Header

    文章学习自:P4语言编程详解 由于原文有一点的年份,所以也继续阅读了相关的最新规范. P4语言规范 基础数据类型 布尔型(bool) 运算符 描述 and 双目运算符,结果为布尔型 or 双目运算符, ...

  4. lintcode-179-更新二进制位

    179-更新二进制位 给出两个32位的整数N和M,以及两个二进制位的位置i和j.写一个方法来使得N中的第i到j位等于M(M会是N中从第i为开始到第j位的子串) 注意事项 In the function ...

  5. cacti添加多个tomcat监控(多端口)

    1.修改tomcat的模版 Data Input Methods->Tomcat Status 把原本固定的端口,用户名和密码手动修改成变量(绿线标出的),之后save保存之后,再在Input ...

  6. Redis 学习之集群

    该文使用centos6.5 64位  redis3.2.8 一.  redis-cluster架构图 集群通信:所有redis节点之间通过PING-PONG机制彼此互联,内部使用二进制鞋子优化传输速度 ...

  7. asp.net中缓存的使用

    刚学到asp.net怎么缓存,这里推荐学习一下 www.cnblogs.com/wang726zq/archive/2012/09/06/cache.html http://blog.csdn.net ...

  8. SP263 PERIOD - Period

    题目描述 For each prefix of a given string S with N characters (each character has an ASCII code between ...

  9. POJ.2142 The Balance (拓展欧几里得)

    POJ.2142 The Balance (拓展欧几里得) 题意分析 现有2种质量为a克与b克的砝码,求最少 分别用多少个(同时总质量也最小)砝码,使得能称出c克的物品. 设两种砝码分别有x个与y个, ...

  10. POJ.1061 青蛙的约会 (拓展欧几里得)

    POJ.1061 青蛙的约会 (拓展欧几里得) 题意分析 我们设两只小青蛙每只都跳了X次,由于他们相遇,可以得出他们同余,则有: 代码总览 #include <iostream> #inc ...