[ONTAK2010] Peaks 加强版

[ONTAK2010] Peaks 加强版

题目大意:原题变为强制在线查询

Solution

  1. 读入山高,排序后依然建立树链,初始化并查集,初始化重构树新节点标号为\(n+1\)
  2. 读入边,按照边权从小到大排序
  3. \(kruskal\)重构树
    • 如果是在同一并查集里,\(continue\)
    • 如果不在,建立新节点,两个节点的\(a\)都是新节点,并且记录在重构树上的\(fa\),合并树链
  4. 倍增处理重构树
  5. 读入询问,如果上一次询问的答案不为\(-1\)\(xor\)上一次的答案,在重构树上跳,查询答案

Code

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#define pf(x) printf("%d\n", x);
using std::sort;

const int X = 3400000 + 5;
const int M = 5e5 + 5;
const int N = 1e5 + 10;

int n, m, q, node, cnt, lastans = 0;
int sum[X], lson[X], rson[X], kfa[N << 1], ju[N << 1][18], val[N], fa[N << 1], root[N << 1];

struct Hill{
	int id, hi;
	bool operator < (const Hill &cmp) const {
		return hi < cmp.hi;
	}
}h[N];

struct Aha{
	int a, b, c;
	bool operator < (const Aha &cmp) const {
		return c < cmp.c;
	}
}a[M];

int find(int x){
	return x == fa[x] ? x : fa[x] = find(fa[x]);
}

void insert(int &cur, int l, int r, int p){
	if(!cur) cur = ++cnt;
	sum[cur]++;
	if(l == r) return;
	int mid = l + ((r - l) >> 1);
	if(p <= mid) insert(lson[cur], l, mid, p);
	else insert(rson[cur], mid + 1, r, p);
}

void merge(int &cur, int x, int y, int l, int r){
	if(!cur) cur = ++cnt;
	sum[cur] = sum[x] + sum[y];
	if(l == r) return;
	int mid = l + ((r - l) >> 1);
	if(lson[x] && lson[y]) merge(lson[cur], lson[x], lson[y], l, mid);
	else if(lson[x]) lson[cur] = lson[x];
	else if(lson[y]) lson[cur] = lson[y];
	if(rson[x] && rson[y]) merge(rson[cur], rson[x], rson[y], mid + 1, r);//1, mid
	else if(rson[x]) rson[cur] = rson[x];
	else if(rson[y]) rson[cur] = rson[y];
}

int query(int cur, int l, int r, int p){
	if(l == r){
		return h[l].hi;//
	}
	int mid = l + ((r - l) >> 1);
	if(p <= sum[lson[cur]]) return query(lson[cur], l, mid, p);
	else return query(rson[cur], mid + 1, r, p - sum[lson[cur]]);

}

inline int jump(int &x, int y){
	for(int i = 17; i >= 0; --i)
		if(ju[x][i] &&  val[ju[x][i] - n] <= y){
			x = ju[x][i];
		} 
	return x;
}

int main(){
	scanf("%d %d %d", &n, &m, &q);
	for(int i = 1; i <= n; ++i)
		scanf("%d", &h[i].hi), h[i].id = i, fa[i] = i;
	sort(h + 1, h + n + 1);
	for(int i = 1; i <= n; ++i)
		insert(root[h[i].id], 1, n, i);
	node = n;
	for(int i = 1; i <= m; ++i)
		scanf("%d %d %d", &a[i].a, &a[i].b, &a[i].c);
	sort(a + 1, a + 1 + m);
	for(int i = 1, fx, fy; i <= m; ++i){
		fx = find(a[i].a);
		fy = find(a[i].b);
		if(fx == fy) continue;
		fa[++node] = fa[fx] = fa[fy] = kfa[fx] = kfa[fy] = node;
		val[node - n] = a[i].c;
		merge(root[node], root[fx], root[fy], 1, n);
	}
	for(int i = 1; i <= node; ++i) ju[i][0] = kfa[i];
	for(int j = 1; j <= 17; ++j)
		for(int i = 1; i <= node; ++i)// i <= n 以及顺序 
			ju[i][j] = ju[ju[i][j - 1]][j - 1];
	int la, lb, lc;
	while(q--){
		scanf("%d %d %d", &la, &lb, &lc);
		if(lastans != -1) la ^= lastans, lb ^= lastans, lc ^= lastans;
		int u = jump(la, lb);
		if(sum[root[u]] < lc) lastans = -1;
		else lastans = query(root[u], 1, n, sum[root[u]] - lc + 1);
		printf("%d\n", lastans);
	}
	return 0;
}
posted @ 2018-09-06 19:01  LMSH7  阅读(95)  评论(0编辑  收藏  举报