• [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
    ", 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
    ", lastans);
    	}
    	return 0;
    }
    
  • 相关阅读:
    读取Exif信息需要对JPEG和Exif格式有简单的了解
    C#图片处理示例(裁剪,缩放,清晰度,水印)
    ArcEngine的两种命令调用形式
    读取GPS信息
    用C#读取图片的EXIF信息的方法
    Arcgis中自定义工具和命令的菜单调用方法及思路
    C# 图片裁剪
    两道题目看MASM汇编
    也看有道第2题,无代码无真相
    [转]微软:C#和CLI将应用“社区承诺协议”&&[转] Mono 这只猴子招惹了谁?
  • 原文地址:https://www.cnblogs.com/LMSH7/p/9600315.html
Copyright © 2020-2023  润新知