「SDOI2013」森林

传送门

树上主席树 + 启发式合并

锻炼码力,没什么好说的。

细节见代码。

参考代码:

#include <algorithm>
#include <cstdio>
#define rg register
#define file(x) freopen(x".in", "r", stdin), freopen(x".out", "w", stdout)
using std ::sort; using std ::swap; using std ::unique; using std ::lower_bound;
inline char _getchar() {
static char buf[100000], *p1 = buf, *p2 = buf;
return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 100000, stdin), p1 == p2) ? EOF : *p1++;
} template < class T > inline void read(T& s) {
s = 0; rg int f = 0; rg char c = _getchar();
while ('0' > c || c > '9') f |= c == '-', c = _getchar();
while ('0' <= c && c <= '9') s = s * 10 + c - 48, c = _getchar();
s = f ? -s : s;
} const int _ = 8e4 + 5; int tot, head[_]; struct Edge { int ver, nxt; } edge[_ << 1];
inline void Add_edge(int u, int v)
{ edge[++tot] = (Edge) { v, head[u] }, head[u] = tot; } int n, m, q, vis[_], a[_], X0, X[_], top[_], Siz[_], fa[18][_], dep[_];
int tt, rt[_]; struct node { int lc, rc, cnt; } t[_ * 266]; inline void build(int& p, int l = 1, int r = X0) {
p = ++tt, t[p].cnt = 0;
if (l == r) return ;
int mid = (l + r) >> 1;
build(t[p].lc, l, mid), build(t[p].rc, mid + 1, r);
} inline void update(int& p, int q, int x, int l = 1, int r = X0) {
p = ++tt, t[p] = t[q], ++t[p].cnt;
if (l == r) return ;
rg int mid = (l + r) >> 1;
if (x <= mid) update(t[p].lc, t[q].lc, x, l, mid);
else update(t[p].rc, t[q].rc, x, mid + 1, r);
} inline int query(int u, int v, int lca, int flca, int k, int l = 1, int r = X0) {
if (l == r) return l;
rg int mid = (l + r) >> 1;
rg int num = t[t[u].lc].cnt + t[t[v].lc].cnt - t[t[lca].lc].cnt - t[t[flca].lc].cnt;
if (num >= k) return query(t[u].lc, t[v].lc, t[lca].lc, t[flca].lc, k, l, mid);
else return query(t[u].rc, t[v].rc, t[lca].rc, t[flca].rc, k - num, mid + 1, r);
} inline void dfs(int u, int f, int topf, int d) {
vis[u] = 1;
dep[u] = d, fa[0][u] = f, top[u] = topf, ++Siz[topf];
rt[u] = 0, update(rt[u], rt[f], a[u]);
for (rg int i = 1; i <= 16; ++i)
fa[i][u] = fa[i - 1][fa[i - 1][u]];
for (rg int i = head[u]; i; i = edge[i].nxt)
if (edge[i].ver != f) dfs(edge[i].ver, u, topf, d + 1);
} inline int LCA(int x, int y) {
if (dep[x] < dep[y]) swap(x, y);
for (rg int i = 16; ~i; --i)
if (dep[fa[i][x]] >= dep[y]) x = fa[i][x];
if (x == y) return x;
for (rg int i = 16; ~i; --i)
if (fa[i][x] != fa[i][y]) x = fa[i][x], y = fa[i][y];
return fa[0][x];
} int main() {
int T; read(T);
read(n), read(m), read(q);
for (rg int i = 1; i <= n; ++i) read(a[i]), X[i] = a[i];
sort(X + 1, X + n + 1);
X0 = unique(X + 1, X + n + 1) - X - 1;
for (rg int i = 1; i <= n; ++i) a[i] = lower_bound(X + 1, X + X0 + 1, a[i]) - X;
build(rt[0]);
for (rg int x, y, o = 1; o <= m; ++o)
read(x), read(y), Add_edge(x, y), Add_edge(y, x);
for (rg int i = 1; i <= n; ++i) if (!vis[i]) dfs(i, 0, i, 1);
for (rg int ans = 0, x, y, k, lca, o = 1; o <= q; ++o) {
rg char C = _getchar();
while (C != 'Q' && C != 'L') C = _getchar();
read(x), x ^= ans;
read(y), y ^= ans;
if (C == 'Q') {
read(k), k ^= ans, lca = LCA(x, y);
ans = X[query(rt[x], rt[y], rt[lca], rt[fa[0][lca]], k)];
printf("%d\n", ans);
} else {
Add_edge(x, y), Add_edge(y, x);
if (Siz[top[x]] < Siz[top[y]]) swap(x, y);
dfs(y, x, top[x], dep[x] + 1);
}
}
return 0;
}

「SDOI2013」森林的更多相关文章

  1. 「luogu2387」[NOI2014] 魔法森林

    「luogu2387」[NOI2014] 魔法森林 题目大意 \(n\) 个点 \(m\) 条边的无向图,每条边上有两个权值 \(a,b\),求从 \(1\) 节点到 \(n\) 节点 \(max\{ ...

  2. 「ZJOI2016」大森林 解题报告

    「ZJOI2016」大森林 神仙题... 很显然线段树搞不了 考虑离线操作 我们只搞一颗树,从位置1一直往后移动,然后维护它的形态试试 显然操作0,1都可以拆成差分的形式,就是加入和删除 因为保证了操 ...

  3. Loj #3056. 「HNOI2019」多边形

    Loj #3056. 「HNOI2019」多边形 小 R 与小 W 在玩游戏. 他们有一个边数为 \(n\) 的凸多边形,其顶点沿逆时针方向标号依次为 \(1,2,3, \ldots , n\).最开 ...

  4. 「ZJOI2016」解题报告

    「ZJOI2016」解题报告 我大浙的省选题真是超级神仙--这套已经算是比较可做的了. 「ZJOI2016」旅行者 神仙分治题. 对于一个矩形,每次我们从最长边切开,最短边不会超过 \(\sqrt{n ...

  5. 「JLOI2015」管道连接 解题报告

    「JLOI2015」管道连接 先按照斯坦纳树求一个 然后合并成斯坦纳森林 直接枚举树的集合再dp一下就好了 Code: #include <cstdio> #include <cct ...

  6. Loj #3102. 「JSOI2019」神经网络

    Loj #3102. 「JSOI2019」神经网络 题目背景 火星探险队发现,火星人的思维方式与人类非常不同,是因为他们拥有与人类很不一样的神经网络结构.为了更好地理解火星人的行为模式,JYY 对小镇 ...

  7. 「数据结构」Link-Cut Tree(LCT)

    #1.0 简述 #1.1 动态树问题 维护一个森林,支持删除某条边,加入某条边,并保证加边.删边之后仍然是森林.我们需要维护这个森林的一些信息. 一般的操作有两点连通性,两点路径权值和等等. #1.2 ...

  8. Solution -「构造」专练

    记录全思路过程和正解分析.全思路过程很 navie,不过很下饭不是嘛.会持续更新的(应该). 「CF1521E」Nastia and a Beautiful Matrix Thought. 要把所有数 ...

  9. 「译」JUnit 5 系列:条件测试

    原文地址:http://blog.codefx.org/libraries/junit-5-conditions/ 原文日期:08, May, 2016 译文首发:Linesh 的博客:「译」JUni ...

随机推荐

  1. Cosmetic Airless Bottles To Meet Practical Requirements

    Today, people use cosmetic bottles, many of which are in cosmetic airless bottles. We can use them, ...

  2. 学习笔记(22)- plato-训练端到端的模型

    原始文档 Train an end-to-end model To get started we can train a very simple model using Ludwig (feel fr ...

  3. Windows配置本地Hadoop运行环境

    很多人喜欢用Windows本地开发Hadoop程序,这里是一个在Windows下配置Hadoop的教程. 首先去官网下载hadoop,这里需要下载一个工具winutils,这个工具是编译hadoop用 ...

  4. MDC 输出线程信息帮助定位问题

    log4j中的%x ---NDC,%X---MDC 即%x NDC.clear();NDC.push(this.toString());%X{first} %X{last}MDC.put(" ...

  5. webjars使用

    目的: Web前端使用了越来越多的JS或CSS,如jQuery,Backbone.js和Bootstrap.一般情况下,我们是将这些Web资源拷贝到Java Web项目的webapp相应目录下进行管理 ...

  6. Codeforces Round #619 (Div. 2) Ayoub's function

    Ayoub thinks that he is a very smart person, so he created a function f(s)f(s) , where ss is a binar ...

  7. location练习!(重点)

    写location最重要的就是hosts文件,添加一次域名跳转就得添加一条hosts文件 hosts文件: 192.168.200.120 www.a.com 192.168.200.119 www. ...

  8. Java连载66-数组的两种初始化方式

    一.数组 1.数组中存储元素的类型是统一的,每一个元素在内存中所占用的空间大小是相同的,知道数组的首元素的内存地址,要查找的元素只要知道下标,就可以快速的计算出偏移量,通过首元素内存地址加上偏移量,就 ...

  9. mysql字符串相关函数(并与sql server对比)

    https://blog.csdn.net/zhengxiuchen86/article/details/81220779 1.判断子串substr在字符串str中出现的位置 例子:查询']'在‘OP ...

  10. iOS开发架构学习记录

    闲着没事看了一些iOS开发架构的视频,简单的介绍了几个常用的架构设计,现将它记录如下,以后有时间再专门写这方面的内容,大家可以看看,感兴趣的就进一步学习. 一.架构基础 1.架构设计的目的 进一步解耦 ...