http://www.lydsy.com/JudgeOnline/problem.php?id=3123 (题目链接)

题意

  给出$n$个点的森林,每个点有一个非负点权,$m$个操作。连接两个点,查询两个点之间路径上的第$K$大点权。强制在线。

Solution

  主席树+启发式合并。

  对于查询操作,主席树维护区间第$K$大即可,当前节点新建的节点是在其父亲节点基础上建立的,也就是说这个主席树维护的是到根的路径。

  对于连接操作,直接启发式合并暴力搞过去就可以了,记得同时更新$size$和$fa$以及重建主席树。

细节

  原来不是多组数据,只是当前数据对应的是数据范围的第几个部分分,好良心的主题人啊→_→

  果然using namespace 就清晰很多,调过样例就直接过了。

代码

// bzoj3123
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<cmath>
#define LL long long
#define lim 1000000000
#define inf 2147483640
#define Pi acos(-1.0)
#define free(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout)
using namespace std; const int maxn=100010;
int Dargen[maxn],size[maxn],deep[maxn],head[maxn],fa[maxn][30],bin[30];
int n,m,Q,sz,ans,cnt,a[maxn],rt[maxn];
struct edge {int to,next;}e[maxn<<1];
struct node {
int son[2],s;
void clear() {son[0]=son[1]=0;s=0;}
int& operator [] (int x) {return son[x];}
}tr[maxn*40]; namespace Chairtree {
void build(int &u,int v,int l,int r,int val) {
if (!u) u=++sz;
if (l==r) {tr[u].s=tr[v].s+1;return;}
int mid=(l+r)>>1;
if (val<=mid) build(tr[u][0],tr[v][0],l,mid,val),tr[u][1]=tr[v][1];
else build(tr[u][1],tr[v][1],mid+1,r,val),tr[u][0]=tr[v][0];
tr[u].s=tr[tr[u][0]].s+tr[tr[u][1]].s;
}
void merge(int x,int y) {
build(rt[x],rt[y],0,lim,a[x]);
Dargen[x]=Dargen[y];fa[x][0]=y;
deep[x]=deep[y]+1;
for (int i=1;i<=20;i++) fa[x][i]=fa[fa[x][i-1]][i-1];
for (int i=head[x];i;i=e[i].next) if (e[i].to!=fa[x][0]) {
merge(e[i].to,x);
size[x]+=size[e[i].to];
}
}
int query(int u,int v,int w,int x,int l,int r,int K) {
if (l==r) return l;
int mid=(l+r)>>1,c=tr[tr[u][0]].s+tr[tr[v][0]].s-tr[tr[w][0]].s-tr[tr[x][0]].s;
if (c>=K) return query(tr[u][0],tr[v][0],tr[w][0],tr[x][0],l,mid,K);
else return query(tr[u][1],tr[v][1],tr[w][1],tr[x][1],mid+1,r,K-c);
}
}
using namespace Chairtree; namespace Tree {
void link(int u,int v) {
e[++cnt]=(edge){v,head[u]};head[u]=cnt;
e[++cnt]=(edge){u,head[v]};head[v]=cnt;
}
void dfs(int x) {
size[x]=1;build(rt[x],rt[fa[x][0]],0,lim,a[x]);
Dargen[x]=fa[x][0] ? Dargen[fa[x][0]] : x;
for (int i=1;i<=20;i++) fa[x][i]=fa[fa[x][i-1]][i-1];
for (int i=head[x];i;i=e[i].next) if (e[i].to!=fa[x][0]) {
fa[e[i].to][0]=x;
deep[e[i].to]=deep[x]+1;
dfs(e[i].to);
size[x]+=size[e[i].to];
}
}
int lca(int x,int y) {
if (deep[x]<deep[y]) swap(x,y);
int t=deep[x]-deep[y];
for (int i=0;bin[i]<=t;i++) if (bin[i]&t) x=fa[x][i];
for (int i=20;i>=0;i--) if (fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i];
return x==y ? x : fa[x][0];
}
}
using namespace Tree; int main() {
char ch[10];int T;scanf("%d",&T);
bin[0]=1;for (int i=1;i<=20;i++) bin[i]=bin[i-1]<<1;
scanf("%d%d%d",&n,&m,&Q);
for (int i=1;i<=n;i++) scanf("%d",&a[i]);
for (int u,v,i=1;i<=m;i++) {
scanf("%d%d",&u,&v);
link(u,v);
}
for (int i=1;i<=n;i++) if (!size[i]) dfs(i);
for (int x,y,K,i=1;i<=Q;i++) {
scanf("%s%d%d",ch,&x,&y);
x^=ans,y^=ans;
if (ch[0]=='L') {
link(x,y);
if (size[Dargen[x]]>size[Dargen[y]]) swap(x,y);
size[Dargen[y]]+=size[Dargen[x]];
merge(x,y);
}
if (ch[0]=='Q') {
scanf("%d",&K);
K^=ans;
int f=lca(x,y);
ans=query(rt[x],rt[y],rt[f],rt[fa[f][0]],0,lim,K);
printf("%d\n",ans);
}
}
return 0;
}

【bzoj3132】 Sdoi2013—森林的更多相关文章

  1. BZOJ 3123: [Sdoi2013]森林 [主席树启发式合并]

    3123: [Sdoi2013]森林 题意:一个森林,加边,询问路径上k小值.保证任意时刻是森林 LCT没法搞,树上kth肯定要用树上主席树 加边?启发式合并就好了,小的树dfs重建一下 注意 测试点 ...

  2. luoguP3302 [SDOI2013]森林 主席树 启发式合并

    题目链接 luoguP3302 [SDOI2013]森林 题解 本来这题树上主席树暴力启发式合并就完了 结果把lca写错了... 以后再也不这么写了 复杂度\(O(nlog^2n)\) "f ...

  3. P3302 [SDOI2013]森林(主席树+启发式合并)

    P3302 [SDOI2013]森林 主席树+启发式合并 (我以前的主席树板子是错的.......坑了我老久TAT) 第k小问题显然是主席树. 我们对每个点维护一棵包含其子树所有节点的主席树 询问(x ...

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

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

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

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

  6. 【BZOJ3123】[Sdoi2013]森林 主席树+倍增LCA+启发式合并

    [BZOJ3123][Sdoi2013]森林 Description Input 第一行包含一个正整数testcase,表示当前测试数据的测试点编号.保证1≤testcase≤20. 第二行包含三个整 ...

  7. 洛谷 P3302 [SDOI2013]森林 解题报告

    P3302 [SDOI2013]森林 题目描述 小\(Z\)有一片森林,含有\(N\)个节点,每个节点上都有一个非负整数作为权值.初始的时候,森林中有\(M\)条边. 小Z希望执行\(T\)个操作,操 ...

  8. 3123: [Sdoi2013]森林

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

  9. bzoj 3123: [Sdoi2013]森林(45分暴力)

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

  10. AC日记——[Sdoi2013]森林 bzoj 3123

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

随机推荐

  1. 2017-2018-2 20155203《网络对抗技术》Exp6 信息搜集与漏洞扫描

    1.实践目标 掌握信息搜集的最基础技能与常用工具的使用方法. 2.实践内容 (1)各种搜索技巧的应用 通过搜索引擎进行信息搜集敏感信息 在百度搜索栏中输入filetype:关键字 site:edu.c ...

  2. [Oracle]跨越 DBLINK 访问表时,数据缓存在何处的Data Buffer 中?

    结论是存储在 remote 端,这其实也很好理解.在远端能高效率地计算,当然应当在远端完成缓存和检索. ■ Before query execution via DBLINK: =========== ...

  3. 汇编 XOR运算

     XOR运算  按位异或^ 一.按位异或^ 运算符^ 1^1=0;0^0=0; //相同则为0 0^1=1;1^0=1; //不相同为1 1101^0110=1011; // asm_XOR.c ...

  4. pygame 入门实例

    本文基于win7(64) + py3.5(64)环境. 本文是这里的一篇学习笔记.加入了自己的理解. 本文最终目的是实现一个飞机躲避导弹的游戏. 1.核心概念 pygame 的核心概念有: Surfa ...

  5. idea 解决 pom.xml 中,maven仓库无法导入的问题(红线)

    只需要用另一篇文章的 maven clean install 功能就行了 idea Cannot Resolve Symbol 问题解决

  6. Security4:授予查看定义,执行SP和只读数据的权限

    SQL Server数据库有完善的权限管理机制,对于存储过程,其权限分为查看定义,执行和修改,查看SP定义的权限是:VIEW DEFINITION ,执行存储过程的权限是:EXECUTE,修改SP的权 ...

  7. java拦截器(Interceptor)学习笔记

    1,拦截器的概念    java里的拦截器是动态拦截Action调用的对象,它提供了一种机制可以使开发者在一个Action执行的前后执行一段代码,也可以在一个Action执行前阻止其执行,同时也提供了 ...

  8. Flutter - 给App增加启动屏幕(Splash Screen)并且设置背景颜色

    先看一下效果图,启动图最好设置为png格式的透明图,以防图片填充不满的时候背景图会非常的煞白(Flutter 默认背景色是白色). 打开android\app\src\main\res\drawabl ...

  9. winform 保存文件 打开文件 选择文件 字体样式颜色(流 using System.IO;)

    string filePath = ""; private void 保存SToolStripMenuItem_Click(object sender, EventArgs e) ...

  10. MOSFET简介以及PMOS和NMOS的差异

    最近在工作中,一直在调试关于MOSFET的电路.在设计过程中发现了PMOS和NMOS的差异,在此记录. 一. MOSFET简介 MOSFET (metal-oxide-semiconductor fi ...