[BZOJ 3123]森林
这题和 COT1 一定有 JQ 喵~
线段树的启发式合并,每次要连接两个点时就对比较小的那棵树暴力 DFS 一边
然后均摊时间依旧是 logn 的,均摊真是世界上最邪恶的东西了……
然后这题的数据是要卖萌么?!
testcase 的存在意义是被阿卡林噎掉了么?!
#include <cstdio>
#include <cstring>
#include <algorithm>
const int sizeOfPoint=;
const int sizeOfEdge=;
const int sizeOfNode=; inline int lg(int);
inline void swap(int & , int & );
inline char getch();
inline int getint();
inline void putint(int); struct edge {int point; edge * next;};
edge memory_edge[sizeOfEdge], * port_edge=memory_edge;
inline edge * newedge(int, edge * );
inline void link(int, int); struct node {int c; node * l , * r; inline node();};
node * null=new node();
node memory_node[sizeOfNode], * port_node=memory_node;
inline node * newnode(node * =null);
node * insert(node * , int, int, int); int b[sizeOfPoint], s[sizeOfPoint];
int find(int);
inline void merge(int, int); int testcase;
int N, M, T, U;
int p[sizeOfPoint], q[sizeOfPoint];
int f[sizeOfPoint], d[sizeOfPoint], a[][sizeOfPoint];
edge * e[sizeOfPoint];
node * t[sizeOfPoint];
inline void clear();
inline bool cmp(int, int);
inline void discretization();
void dfs(int);
inline int lca(int, int);
inline int query(int, int, int); int main()
{
int lastans=; testcase=getint();
for (testcase=;testcase;testcase--)
{
N=getint(), M=getint(), T=getint();
clear();
for (int i=;i<=N;i++)
p[i]=getint();
for (int i=;i<=M;i++)
{
int u=getint(), v=getint();
link(u, v);
}
discretization(); for (int i=;i<=N;i++) if (f[i]==-)
{
f[i]=; d[i]=;
dfs(i);
} for (int i=;i<=T;i++)
{
char c=getch(); int x=getint()^lastans, y=getint()^lastans;
if (c=='Q')
{
int k=getint()^lastans;
lastans=query(x, y, k);
putint(lastans);
}
else
{
int bx=find(x), by=find(y);
if (bx==by) continue;
if (s[bx]<s[by]) swap(x, y);
link(x, y);
f[y]=x; d[y]=d[x]+;
dfs(y);
}
}
} return ;
} inline int lg(int x)
{
return -__builtin_clz(x);
}
inline void swap(int & x, int & y)
{
int z=x;
x=y;
y=z;
}
inline char getch()
{
register char ch;
do ch=getchar(); while (ch!='L' && ch!='Q');
return ch;
}
inline int getint()
{
register int num=;
register char ch=, last;
do last=ch, ch=getchar(); while (ch<'' || ch>'');
do num=num*+ch-'', ch=getchar(); while (ch>='' && ch<='');
if (last=='-') num=-num;
return num;
}
inline void putint(int num)
{
char stack[];
register int top=;
if (num==) stack[top=]='';
if (num<) putchar('-'), num=-num;
for ( ;num;num/=) stack[++top]=num%+'';
for ( ;top;top--) putchar(stack[top]);
putchar('\n');
} inline edge * newedge(int point, edge * next)
{
edge * ret=port_edge++;
ret->point=point; ret->next=next;
return ret;
}
inline void link(int u, int v)
{
e[u]=newedge(v, e[u]);
e[v]=newedge(u, e[v]);
merge(u, v);
} inline node::node()
{
this->c=;
this->l=this;
this->r=this;
}
inline node * newnode(node * t)
{
node * newt=port_node++;
*newt=*t;
return newt;
}
node * insert(node * t, int l, int r, int k)
{
t=newnode(t);
t->c++;
if (l==r) return t; int m=(l+r)>>;
if (k<=m) t->l=insert(t->l, l, m, k);
else t->r=insert(t->r, m+, r, k);
return t;
} int find(int u)
{
return !b[u]?u:b[u]=find(b[u]);
}
inline void merge(int u, int v)
{
u=find(u); v=find(v);
b[v]=u; s[u]+=s[v];
} inline void clear()
{
port_edge=memory_edge;
memset(e, , sizeof(e));
port_node=memory_node;
for (int i=;i<=N;i++) t[i]=null;
memset(f, -, sizeof(f));
memset(d, -, sizeof(d));
memset(b, , sizeof(b));
memset(a, , sizeof(a));
for (int i=;i<=N;i++) s[i]=;
}
inline bool cmp(int a, int b)
{
return p[a]<p[b];
}
inline void discretization()
{
static int k[sizeOfPoint]; for (int i=;i<=N;i++) k[i]=i;
std::sort(k+, k+N+, cmp); q[U=]=p[k[]]; p[k[]]=;
for (int i=;i<=N;i++)
{
if (p[k[i]]>q[U]) q[++U]=p[k[i]];
p[k[i]]=U;
}
}
void dfs(int u)
{
t[u]=insert(t[f[u]], , U, p[u]);
if (d[u]>)
{
int lim=lg(d[u]);
a[][u]=f[u];
for (int i=;i<=lim;i++)
a[i][u]=a[i-][a[i-][u]];
for (int i=lim+;i<;i++)
a[i][u]=;
} for (edge * i=e[u];i;i=i->next) if (i->point!=f[u])
{
f[i->point]=u;
d[i->point]=d[u]+;
dfs(i->point);
}
}
inline int lca(int u, int v)
{
if (d[u]<d[v]) swap(u, v);
while (int dist=d[u]-d[v]) u=a[__builtin_ctz(dist)][u];
if (u==v) return u;
for (int i=;i>=;i--)
if (a[i][u]!=a[i][v])
u=a[i][u],
v=a[i][v];
return f[u];
}
inline int query(int a, int b, int k)
{
int c=lca(a, b), d=f[c];
node * ta=t[a], * tb=t[b], * tc=t[c], * td=t[d];
int l=, r=U, m; for ( ;l<r; )
{
m=(l+r)>>;
if (ta->l->c+tb->l->c-tc->l->c-td->l->c>=k)
{
ta=ta->l; tb=tb->l; tc=tc->l; td=td->l;
r=m;
}
else
{
k-=ta->l->c+tb->l->c-tc->l->c-td->l->c;
ta=ta->r; tb=tb->r; tc=tc->r; td=td->r;
l=m+;
}
} return q[l];
}
又 R 又 T 一时爽
[BZOJ 3123]森林的更多相关文章
- BZOJ 3123 森林(函数式线段树)
题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=3123 题意: 思路:总的来说,查询区间第K小利用函数式线段树的减法操作.对于两棵树的合并 ...
- BZOJ - 3123 森林 (可持久化线段树+启发式合并)
题目链接 先把初始边建成一个森林,每棵树选一个根节点递归建可持久化线段树.当添加新边的时候,把结点数少的树暴力重构,以和它连边的那个点作为父节点继承线段树,并求出倍增数组.树的结点数可以用并查集来维护 ...
- [BZOJ 3123] [SDOI 2013]森林(可持久化线段树+并查集+启发式合并)
[BZOJ 3123] [SDOI 2013]森林(可持久化线段树+启发式合并) 题面 给出一个n个节点m条边的森林,每个节点都有一个权值.有两种操作: Q x y k查询点x到点y路径上所有的权值中 ...
- 【sdoi2013】森林 BZOJ 3123
Input 第一行包含一个正整数testcase,表示当前测试数据的测试点编号.保证1≤testcase≤20. 第二行包含三个整数N,M,T,分别表示节点数.初始边数.操作数.第三行包含N个非负整数 ...
- BZOJ 3123: [Sdoi2013]森林 [主席树启发式合并]
3123: [Sdoi2013]森林 题意:一个森林,加边,询问路径上k小值.保证任意时刻是森林 LCT没法搞,树上kth肯定要用树上主席树 加边?启发式合并就好了,小的树dfs重建一下 注意 测试点 ...
- bzoj 3123: [Sdoi2013]森林(45分暴力)
3123: [Sdoi2013]森林 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 4184 Solved: 1235[Submit][Status ...
- AC日记——[Sdoi2013]森林 bzoj 3123
3123: [Sdoi2013]森林 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 3216 Solved: 944[Submit][Status] ...
- Bzoj 3123: [Sdoi2013]森林(主席树+启发式合并)
3123: [Sdoi2013]森林 Time Limit: 20 Sec Memory Limit: 512 MB Description Input 第一行包含一个正整数testcase,表示当前 ...
- ●BZOJ 3123 [Sdoi2013]森林
题链: http://www.lydsy.com/JudgeOnline/problem.php?id=3123 题解: 主席树,在线,启发式合并 简单版(只有询问操作):[2588: Spoj 10 ...
随机推荐
- ArrayList和Vector的区别
3.ArrayList和Vector的区别 答: 这两个类都实现了List接口(List接口继承了Collection接口),他们都是有序集合,即存储在这两个集合中的元素的位置都是有顺序的,相当于一种 ...
- 关于mongodb的复合索引新功能
最新在做一个项目,由于查询字段较多,且查询较频繁,所以我做了一个复合索引,将所有需要查询的字段都做到索引里,做了一个名为s_1_m_1_c_1_v_1_year_1_month_1_week_1_da ...
- selenium配置
1.firebug安装--火狐插件 2.firepath安装--火狐插件 3.
- odi 12.2.1中访问excel文件
由于在odi 12.2.1中,必须使用jdk1.8,而jdk1.8中jdbc-odbc bridge已经不再支持,因此,可以使用Progress DataDirect SequeLink来充当jdbc ...
- Java Json Object 互转
官方网址: http://json-lib.sourceforge.net/ 需要准备的jar包 1. json-lib-2.4-jdk15.jar 目前最新版, 下载地址 http: ...
- javascript语言精粹
内容选自:<javascript语言精粹> 1.6种值会为假(==false),分别是false,null,undefined,' ',0,NaN 2.typeof有6种值,分别是'num ...
- C++网络编程之select
select函数决定一个或者多个套接字(socket)的状态,如果需要的话,等待执行异步I/O. int select( __in int nfds, __inout fd_ ...
- SSH中,使用Filter拦截直接访问JSP页面!
话不多说,直接上代码 创建一个Filter类 package com.weibo.util; import java.io.IOException; import javax.servlet.Filt ...
- php大力力:技术排错过程中,关键点总结和心情历程(2015-10-19)
9:40 2015/10/19技术排错过程中,关键点总结和心情历程 有一个按照标题进行内容分类的函数似乎不起作用,这叫人沮丧. 在页面显示图片地址时候,在源系统和目标系统中,包含图片地址的页面代码格式 ...
- MyBatis 配置文件头部换行异常
INFO - Destroying singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory ...