博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
bzoj 3551
阅读量:5079 次
发布时间:2019-06-12

本文共 3718 字,大约阅读时间需要 12 分钟。

按照困难度升序排序

Kruskal重构树
这样一来一个点的子树中的所有困难值都小于改点的困难值
对于每次询问
倍增找出困难值最大且小于x的点
该点的子树中的第k大就是询问的答案
主席书维护区间k大

#include 
#include
#include
#include
#include
using namespace std;const int N = 1e5 + 10, M = 2e5 + 10;int n, m, Q;int A[N << 1], high[N << 1], val[N << 1];struct Node { int u, v, hard;} Edge[M * 10];struct Node_ { int v, nxt;} G[M * 10];int fa[N << 1];int Root[N << 1];int W[M * 10];int head[N << 1];int Lson[M * 10], Rson[M * 10];int now;int tree[N << 1], bef[N << 1], lst[N << 1], rst[N << 1], Tree;int N_;int f[N << 1][30];int Ans;int Segjs;int impjs;#define gc getchar()inline int read() { int x = 0; char c = gc; while(c < '0' || c > '9') c = gc; while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = gc; return x;}inline bool Cmp(Node a, Node b) { return a.hard < b.hard;}int Get(int x) { return fa[x] == x ? x : fa[x] = Get(fa[x]);}inline void Add(int u, int v) { G[++ now].v = v; G[now].nxt = head[u]; head[u] = now;}inline void Pre() { for(int i = 1; i <= 20; i ++) for(int j = 1; j <= n * 2 - 1; j ++) f[j][i] = f[f[j][i - 1]][i - 1];}inline void Fill(int x, int y) { Lson[x] = Lson[y], Rson[x] = Rson[y], W[x] = W[y];}inline int Imp_find(int u, int x) { for(int i = 20; i >= 0; i --) if(f[u][i] && val[f[u][i]] <= x) u = f[u][i]; return u;}inline void Kruskal() { sort(Edge + 1, Edge + m + 1, Cmp); impjs = n; for(int i = 1; i <= n * 2; i ++) fa[i] = i; for(int i = 1; i <= n * 2; i ++) head[i] = -1; for(int i = 1; i <= m; i ++) { int fau = Get(Edge[i].u), fav = Get(Edge[i].v); if(fau != fav) { impjs ++; val[impjs] = Edge[i].hard; fa[fau] = fa[fav] = impjs; Add(impjs, fau), Add(fau, impjs), Add(impjs, fav), Add(fav, impjs); } if(impjs == n * 2 - 1) break; }}void Dfs(int u, int fa) { if(u <= n) { lst[u] = rst[u] = ++ Tree; bef[Tree] = u; } else lst[u] = n; for(int i = head[u]; ~ i; i = G[i].nxt) { int v = G[i].v; if(v == fa) continue; f[v][0] = u; Dfs(v, u); rst[u] = max(rst[u], rst[v]), lst[u] = min(lst[u], lst[v]); }}void Insert(int &rt, int l, int r, int x) { Fill(++ Segjs, rt); rt = Segjs; W[rt] ++; if(l == r) return ; int mid = (l + r) >> 1; if(x <= mid) Insert(Lson[rt], l, mid, x); else Insert(Rson[rt], mid + 1, r, x);}void Sec_A(int jd1, int jd2, int l, int r, int k) { if(l == r) {Ans = l; return ;} if(W[jd2] - W[jd1] < k) {Ans = -1; return ;} int mid = (l + r) >> 1; if(W[Rson[jd2]] - W[Rson[jd1]] >= k) Sec_A(Rson[jd1], Rson[jd2], mid + 1, r, k); else Sec_A(Lson[jd1], Lson[jd2], l, mid, k - (W[Rson[jd2]] - W[Rson[jd1]]));}int main() { n = read(), m = read(), Q = read(); for(int i = 1; i <= n; i ++) A[i] = read(), high[i] = A[i]; for(int i = 1; i <= m; i ++) { int a = read(), b = read(), c = read(); Edge[i] = (Node) {a, b, c}; } sort(A + 1, A + n + 1); int a = unique(A + 1, A + n + 1) - A - 1; for(int i = 1; i <= n; i ++) high[i] = lower_bound(A + 1, A + a + 1, high[i]) - A; Kruskal(); Dfs(impjs, 0); Pre(); for(int i = 1; i <= n; i ++) { Root[i] = Root[i - 1]; Insert(Root[i], 1, n, high[bef[i]]); } for(; Q; Q --) { int v = read(), x = read(), k = read(); if(Ans != -1) v ^= Ans, x ^= Ans, k ^= Ans; int use = Imp_find(v, x); Sec_A(Root[lst[use] - 1], Root[rst[use]], 1, n, k); if(Ans != -1) Ans = A[Ans]; printf("%d\n", Ans); } return 0;}

 

转载于:https://www.cnblogs.com/shandongs1/p/9499681.html

你可能感兴趣的文章
Ubuntu 16.04 LTS今日发布
查看>>
mybatis 中test里面 应该为单引号套双引号
查看>>
修改flash builder注释里的@author
查看>>
Unity3D优化总结(一)
查看>>
Apache ActiveMQ 学习一
查看>>
Spring框架最简单的定时任务调用
查看>>
Minify or format javascript file by web or notepad++
查看>>
eclipse html 打开方式
查看>>
java注解实例-反射生成sql
查看>>
Web前端工程师常去的15个技术网站
查看>>
【BZOJ4373】算术天才⑨与等差数列 [线段树]
查看>>
Oracle学习 第8天
查看>>
4.6下午 张涛听力3.14
查看>>
3.Git基础-查看当前文件状态、跟踪新文件、暂存文件、忽略文件、提交更新、移除文件、移动文件...
查看>>
二分法查找
查看>>
Linux时间设置
查看>>
7-11
查看>>
vue---day02
查看>>
windows下使用mingw和msys编译GOTOBLAS和OpenBLAS
查看>>
sql server 函数详解(5)系统函数
查看>>