题面传送门


复出的第一道题.. md就遇到坑了..

简单来说就是可持久化线段树+启发式合并啊..

感觉启发式合并好神奇好想学

每一次建边就暴力合并,每一个节点维护从根到它的权值线段树

按照题面的话最省空间的做法就是垃圾回收,但是实在是太慢了..

而且这题有坑,题面说的是多组数据其实只有一组 而且是$T>1$的一组..

然后看给了512MB就不需要垃圾回收,而且很多预处理都tm不用了呢!wqnmdsy

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
using namespace std;
const int Maxn = 80010;
const int lg = 18;
struct node {
int y, next;
}a[Maxn*2]; int first[Maxn], len;
void ins ( int x, int y ){
len ++;
a[len].y = y;
a[len].next = first[x]; first[x] = len;
}
int n, m, t;
int sum[Maxn*lg*lg], lc[Maxn*lg*lg], rc[Maxn*lg*lg], tot;
int rt[Maxn];
int na[Maxn], b[Maxn], bl;
int fa[Maxn][lg], dep[Maxn];
int faa[Maxn], gs[Maxn];
int ff ( int x ){
if ( faa[x] == x ) return x;
return faa[x] = ff (faa[x]);
}
void merge ( int &now, int fnow, int l, int r, int x ){
if ( !now ) now = ++tot;
sum[now] = sum[fnow]+1;
if ( l == r ) return;
int mid = ( l + r ) >> 1;
if ( x <= mid ) merge ( lc[now], lc[fnow], l, mid, x ), rc[now] = rc[fnow];
else merge ( rc[now], rc[fnow], mid+1, r, x ), lc[now] = lc[fnow];
}
void dfs1 ( int x, int f ){
rt[x] = 0;
merge ( rt[x], rt[fa[x][0]], 1, bl, na[x] );
for ( int i = 1; i <= 17; i ++ ) fa[x][i] = fa[fa[x][i-1]][i-1];
for ( int k = first[x]; k; k = a[k].next ){
int y = a[k].y;
if ( y == f ) continue;
fa[y][0] = x; dep[y] = dep[x]+1;
dfs1 ( y, x );
}
}
void change ( int &now, int l, int r, int x ){
if ( !now ) now = ++tot;
sum[now] ++;
if ( l == r ) return;
int mid = ( l + r ) >> 1;
if ( x <= mid ) change ( lc[now], l, mid, x );
else change ( rc[now], mid+1, r, x );
}
int getlca ( int x, int y ){
if ( dep[x] < dep[y] ) swap ( x, y );
for ( int i = 17; i >= 0; i -- ){
if ( dep[fa[x][i]] >= dep[y] ){
x = fa[x][i];
}
}
if ( x == y ) return x;
for ( int i = 17; i >= 0; i -- ){
if ( fa[x][i] != fa[y][i] ){
x = fa[x][i]; y = fa[y][i];
}
}
return fa[x][0];
}
int getrank ( int now1, int now2, int now3, int p, int l, int r, int k ){
if ( l == r ) return b[l];
int mid = ( l + r ) >> 1;
int ls = sum[lc[now1]]+sum[lc[now2]]-2*sum[lc[now3]];
if ( na[p] <= mid && na[p] >= l ) ls --;
if ( ls >= k ) return getrank ( lc[now1], lc[now2], lc[now3], p, l, mid, k );
else return getrank ( rc[now1], rc[now2], rc[now3], p, mid+1, r, k-ls );
}
void read ( int &x ){
char c = getchar ();
for ( ; c > '9' || c < '0'; c = getchar () );
x = 0;
for ( ; c <= '9' && c >= '0'; c = getchar () ) x = x*10+c-'0';
}
int main (){
int i, j, k, T;
read (T);
tot = 0;
while ( T -- ){
len = 0; memset ( first, 0, sizeof (first) );
read (n); read (m); read (t);
for ( i = 1; i <= n; i ++ ) rt[i] = 0, faa[i] = i, gs[i] = 1, dep[i] = 1;
for ( i = 1; i <= n; i ++ ){
read (na[i]);
b[i] = na[i];
}
sort ( b+1, b+n+1 );
bl = unique ( b+1, b+n+1 ) - (b+1);
for ( i = 1; i <= n; i ++ ){
na[i] = lower_bound ( b+1, b+bl+1, na[i] ) - b;
change ( rt[i], 1, bl, na[i] );
}
for ( i = 1; i <= m; i ++ ){
int x, y;
read (x); read (y);
int fx = ff (x), fy = ff (y);
if ( gs[fx] > gs[fy] ) swap ( x, y );
faa[fx] = fy; gs[fy] += gs[fx];
fa[x][0] = y; dep[x] = dep[y]+1;
dfs1 ( x, y );
ins ( x, y ); ins ( y, x );
}
char c;
int lastans = 0;
while ( t -- ){
c = getchar ();
for ( ; c > 'Z' || c < 'A'; c = getchar () );
if ( c == 'Q' ){
int x, y;
read (x); read (y); read (k);
x ^= lastans; y ^= lastans; k ^= lastans;
int lca = getlca ( x, y );
lastans = getrank ( rt[x], rt[y], rt[fa[lca][0]], lca, 1, bl, k );
printf ( "%d\n", lastans );
}
else {
int x, y;
read (x); read (y);
x ^= lastans; y ^= lastans;
int fx = ff (x), fy = ff (y);
if ( gs[fx] > gs[fy] ) swap ( x, y );
faa[fx] = fy; gs[fy] += gs[fx];
fa[x][0] = y; dep[x] = dep[y]+1;
dfs1 ( x, y );
ins ( x, y ); ins ( y, x );
}
}
break;
}
return 0;
}

  

bzoj3123: [Sdoi2013]森林的更多相关文章

  1. [bzoj3123][Sdoi2013]森林_主席树_启发式合并

    森林 bzoj-3123 Sdoi-2013 题目大意:给定一片共n个点的森林,T个操作,支持:连接两个不在一棵树上的两个点:查询一棵树上路径k小值. 注释:$1\le n,T \le 8\cdot ...

  2. [BZOJ3123][Sdoi2013]森林 主席树+启发式合并

    3123: [Sdoi2013]森林 Time Limit: 20 Sec  Memory Limit: 512 MB Description Input 第一行包含一个正整数testcase,表示当 ...

  3. BZOJ3123: [Sdoi2013]森林(启发式合并&主席树)

    3123: [Sdoi2013]森林 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 4813  Solved: 1420[Submit][Status ...

  4. [bzoj3123][sdoi2013森林] (树上主席树+lca+并查集启发式合并+暴力重构森林)

    Description Input 第一行包含一个正整数testcase,表示当前测试数据的测试点编号.保证1≤testcase≤20. 第二行包含三个整数N,M,T,分别表示节点数.初始边数.操作数 ...

  5. 【主席树 启发式合并】bzoj3123: [Sdoi2013]森林

    小细节磕磕碰碰浪费了半个多小时的时间 Description Input 第一行包含一个正整数testcase,表示当前测试数据的测试点编号.保证1≤testcase≤20. 第二行包含三个整数N,M ...

  6. BZOJ3123[Sdoi2013]森林——主席树+LCA+启发式合并

    题目描述 输入 第一行包含一个正整数testcase,表示当前测试数据的测试点编号.保证1≤testcase≤20. 第二行包含三个整数N,M,T,分别表示节点数.初始边数.操作数.第三行包含N个非负 ...

  7. bzoj千题计划258:bzoj3123: [Sdoi2013]森林

    http://www.lydsy.com/JudgeOnline/problem.php?id=3123 启发式合并主席树 #include<cmath> #include<cstd ...

  8. [bzoj3123] [SDOI2013]森林 主席树+启发式合并+LCT

    Description Input 第一行包含一个正整数testcase,表示当前测试数据的测试点编号.保证1≤testcase≤20. 第二行包含三个整数N,M,T,分别表示节点数.初始边数.操作数 ...

  9. bzoj3123 [Sdoi2013]森林 树上主席树+启发式合并

    题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=3123 题解 如果是静态的查询操作,那么就是直接树上主席树的板子. 但是我们现在有了一个连接两棵 ...

随机推荐

  1. Sicily 1051: 魔板(BFS+排重)

    相对1150题来说,这道题的N可能超过10,所以需要进行排重,即相同状态的魔板不要重复压倒队列里,这里我用map储存操作过的状态,也可以用康托编码来储存状态,这样时间缩短为0.03秒.关于康托展开可以 ...

  2. 微信小程序常见错误及基本排除方法

    也接触了不少人解决问题的过程里,有一些比较难以排查的可能性列举在这,方便大家看一下:   也欢迎大家把自己常用的排除方法列举在这,一起互相学习探讨!1:ES6:使用es6可能导致安卓端真机调试时很多问 ...

  3. C#数字日期装换为中文日期

    using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace Cons ...

  4. [恶趣味]搞了下局域网内的arp网络欺骗

    挺无聊的. 扫描,伪装,抓包. 基本上搞完就失去乐趣了. 文章在这里,想搞的可以自己拿去搞下,其实很无聊,我真是个很容易无聊的人啊.

  5. 通过rsync+inotify实现数据的实时备份

    我讲到过利用rsync实现数据的镜像和备份,但是要实现数据的实时备份,单独靠rsync还不能实现,本文就讲述下如何实现数据的实时备份. 一.rsync的优点与不足 与传统的cp.tar备份方式相比,r ...

  6. sudo:有效用户 ID 不是 0,sudo 属于 root 并设置了 setuid 位吗

    遇见这种问题应该检查sudo文件拥有者名称 ---x--x--x. 1 cmp cmp 130720  sudo 明显拥有者有问题 chown root:root /usr/bin/sudo chmo ...

  7. 卷积神经网络_(4)_caffe简介

    这里大致说一下caffe.caffe是伯里克利大学的贾杨清教授写的一个深度学习框架,使用C++编写的,但同时也提供python和matlab接口:组成部分主要有: (1)Blob:用来存储数据和梯度: ...

  8. Oracle基础知识(一)、简介与安装

    文章提纲 Oracle简介与发展历程 安装实例(面向普通开发者) 一.Oracle简介与发展历程 中文名称甲骨文公司,全称为甲骨文股份有限公司(甲骨文软件系统有限公司).甲骨文已超越 IBM ,成为继 ...

  9. JSP复习整理(二)基本语法

    最基础的整理.. 一.语句声明 <%@ page language="java" contentType="text/html; charset=UTF-8&quo ...

  10. 学号20145332 《信息安全系统设计基础》实验五 简单嵌入式WEB服务器实验

    实验目的 掌握在 ARM 开发板实现一个简单 WEB 服务器的过程. 学习在 ARM 开发板上的 SOCKET 网络编程. 学习 Linux 下的 signal()函数的使用. 实验内容 学习使用 s ...