「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. max=(a>b)?a:b;

    这个函数的意思是如果a>b,max=a:否则max=b. 实际程序: while ((__HAL_UART_GET_FLAG(huart, Flag) ? SET : RESET) == Sta ...

  2. 吴裕雄 python 神经网络——TensorFlow 三层简单神经网络的前向传播算法

    import tensorflow as tf w1= tf.Variable(tf.random_normal([2, 3], stddev=1, seed=1)) w2= tf.Variable( ...

  3. 吴裕雄 PYTHON 人工智能——基于MASK_RCNN目标检测(4)

    import os import sys import random import math import re import time import numpy as np import tenso ...

  4. appium 无法通过工具定位webview页面元素的问题

    app里面页面有原生和webview的,或者H5的 1.手机百度搜索结果页面 手机百度,点击搜索输入框,输入关键字点击搜索,出来的搜索结果页面,无法通过UI automator viewer来定位元素 ...

  5. Mybatis 的分页插件 PageHelper

    我用的版本是PageHelper-4.1.1.Mybatis-3.3.0 PageHelper 依赖于 jsqlparser-0.9.4.jar   使用方法: 1.根据Mybatis的版本下载对应版 ...

  6. dp(多重背包)

    有 NN 种物品和一个容量是 VV 的背包. 第 ii 种物品最多有 sisi 件,每件体积是 vivi ,价值是 wiwi . 求解将哪些物品装入背包,可使物品体积总和不超过背包容量,且价值总和最大 ...

  7. mysql的一些不常用语句

    今天写项目,用的ThinkPHP,写的时候有点费劲,原因嘛 无非是对框架或者mysql的一些知识的遗忘. 1.为了配合ThinkPHP中的控制器,需要修改数据库中表名,一时想不起来,幸好有百度,问题很 ...

  8. pytest+allure(allure-pytest基于这个插件)设计定制化报告

    一:环境准备 1.python3.6 2.windows环境 3.pycharm 4.allure-pytest 5.allure2.8.0 6.java1.8 allure-pytest快速安装 在 ...

  9. 模仿虎牙App 导航栏切换

    昨天看虎牙直播,发现导航栏挺有意思,自己也做个玩玩 <view class="tab_list row"> <view class="tab_item ...

  10. 在Ubuntu_meta 16.04中设置默认Python3.5的命令

    ubuntu_meta 默认是安装了python2.7 和python3.5两个版本 查看ubuntu的python版本,默认版本是python2.7 输入:python 直接执行这两个命令即可: s ...