题意:一个带点权的森林,要求维护以下操作:

1.询问路径上的点权K大值

2.两点之间连边

n,m<=80000

思路:如果树的结构不发生变化只需要维护DFS序

现在因为树的结构发生变化,要将两棵树合并,这步可以用启发式合并,将比较小的树暴力连接到较大的树上面

离线的LCA算法无法维护,而倍增可以合并,所以用倍增求LCA

其余就是主席树,维护根到点的权值线段树就行了

机房里的罗爷爷写法比我高到不知道哪里去了

 #include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int M=;
int cas,n,m,q,i,x,y,k,edgenum,cnt,ans;
int a[M],b[M],c[M],head[M],vet[M],next[M],dep[M],fa[M][],f[M],size[M],root[M];
struct node{int l,r,w;}tree[M*];
bool cmp(int x,int y){return a[x]<a[y];}
int search(int x){
if (f[x]!=x)f[x]=search(f[x]);
return f[x];
}
void addedge(int x,int y){
vet[++edgenum]=y;
next[edgenum]=head[x];
head[x]=edgenum;
}
void update(int x,int l,int r,int &p){
tree[++cnt]=tree[p];p=cnt;tree[p].w++;
if (l==r)return;
int mid=l+r>>;
if (x<=mid)update(x,l,mid,tree[p].l);
else update(x,mid+,r,tree[p].r);
}
int query(int l,int r,int k,int x,int y,int z,int w){
if (l==r)return l;
int mid=l+r>>,t=tree[tree[x].l].w+tree[tree[y].l].w-tree[tree[z].l].w-tree[tree[w].l].w;
if (t>=k)return query(l,mid,k,tree[x].l,tree[y].l,tree[z].l,tree[w].l);
else return query(mid+,r,k-t,tree[x].r,tree[y].r,tree[z].r,tree[w].r);
}
int lca(int x,int y){
if (dep[x]<dep[y])swap(x,y);
int t=dep[x]-dep[y];
for (int i=;i<=;i++)
if (t&(<<i))x=fa[x][i];
for (int i=;i>=;i--)
if (fa[x][i]!=fa[y][i])x=fa[x][i],y=fa[y][i];
if (x==y)return x;
return fa[x][];
}
void dfs(int u,int pre){
fa[u][]=pre;
for (int i=;i<=;i++)fa[u][i]=fa[fa[u][i-]][i-];
root[u]=root[pre];
update(c[u],,n,root[u]);
for (int e=head[u];e;e=next[e]){
int v=vet[e];
if (v==pre)continue;
dep[v]=dep[u]+;
dfs(v,u);
}
}
void link(int x,int y){
int p=search(x),q=search(y);
if (size[p]>size[q]){swap(x,y);swap(p,q);}
dep[x]=dep[y]+;
dfs(x,y);
f[p]=q;size[q]+=size[p];
addedge(x,y);
addedge(y,x);
}
int main(){
scanf("%d",&cas);
scanf("%d%d%d",&n,&m,&q);
for (i=;i<=n;i++)scanf("%d",&a[i]),b[i]=i;
sort(b+,b+n+,cmp);
for (i=;i<=n;i++)c[b[i]]=i;
for (i=;i<=n;i++)f[i]=i,size[i]=;
cnt=n;
for (i=;i<=n;i++)root[i]=i,update(c[i],,n,root[i]);
for (i=;i<=m;i++){
scanf("%d%d",&x,&y);
link(x,y);
}
while (q--){
char s[];
scanf("%s",s);
if (s[]=='L'){
scanf("%d%d",&x,&y);
x^=ans;y^=ans;
link(x,y);
}else{
scanf("%d%d%d",&x,&y,&k);
x^=ans;y^=ans;k^=ans;
int z=lca(x,y);
printf("%d\n",ans=a[b[query(,n,k,root[x],root[y],root[z],root[fa[z][]])]]);
}
}
}

这是我的萎靡写法

 var t:array[..]of record
l,r,s:longint;
end;
f:array[..,..]of longint;
root,head,c,a,hash,h,dep,stk,size:array[..]of longint;
vet,next:array[..]of longint;
n,m,x,y,z,lastans,i,j,tot,cnt,k,s,up,top,que:longint;
ch:string; procedure swap(var x,y:longint);
var t:longint;
begin
t:=x; x:=y; y:=t;
end; procedure qsort(l,r:longint);
var i,j,mid:longint;
begin
i:=l; j:=r; mid:=c[(l+r)>>];
repeat
while mid>c[i] do inc(i);
while mid<c[j] do dec(j);
if i<=j then
begin
swap(c[i],c[j]);
inc(i); dec(j);
end;
until i>j;
if l<j then qsort(l,j);
if i<r then qsort(i,r);
end; function lsh(x:longint):longint;
var l,r,mid:longint;
begin
l:=; r:=up;
while l<=r do
begin
mid:=(l+r)>>;
if x=hash[mid] then exit(mid);
if x<hash[mid] then r:=mid-
else l:=mid+;
end;
end; function find(k:longint):longint;
begin
if h[k]<>k then h[k]:=find(h[k]);
exit(h[k]);
end; procedure add(a,b:longint);
begin
inc(tot);
next[tot]:=head[a];
vet[tot]:=b;
head[a]:=tot;
end; procedure pushup(p:longint);
begin
t[p].s:=t[t[p].l].s+t[t[p].r].s;
end; procedure update(l,r,x:longint;var y:longint;v:longint);
var mid:longint;
begin
inc(cnt); y:=cnt;
t[y]:=t[x]; inc(t[y].s);
if l=r then exit;
mid:=(l+r)>>;
if v<=mid then update(l,mid,t[x].l,t[y].l,v)
else update(mid+,r,t[x].r,t[y].r,v);
pushup(y);
end; procedure dfs(u,pre:longint);
var e,v,x,y:longint;
begin
update(,up,root[pre],root[u],a[u]);
e:=head[u];
dep[u]:=dep[pre]+;
f[u,]:=pre;
while e<> do
begin
v:=vet[e];
if v<>pre then
begin
dfs(v,u);
x:=find(v); y:=find(u);
if size[x]<size[y] then
begin
size[x]:=size[y]+size[x];
h[y]:=x;
end
else begin size[y]:=size[x]+size[y]; h[x]:=y; end;
end;
e:=next[e];
end;
end; function lca(x,y:longint):longint;
var i,d:longint;
begin
if dep[x]<dep[y] then swap(x,y);
d:=dep[x]-dep[y];
for i:= to do
if d and (<<i)> then x:=f[x,i];
for i:= downto do
if f[x,i]<>f[y,i] then
begin
x:=f[x,i]; y:=f[y,i];
end;
if x=y then exit(x);
exit(f[x,]);
end; function query(l,r,x,y,z,w,k:longint):longint;
var mid,tmp:longint;
begin
if l=r then exit(l);
mid:=(l+r)>>;
tmp:=t[t[x].l].s+t[t[y].l].s-t[t[z].l].s-t[t[w].l].s;
if tmp>=k then
begin
x:=t[x].l; y:=t[y].l; z:=t[z].l; w:=t[w].l;
exit(query(l,mid,x,y,z,w,k));
end
else
begin
x:=t[x].r; y:=t[y].r; z:=t[z].r; w:=t[w].r;
exit(query(mid+,r,x,y,z,w,k-tmp));
end;
end; function ask(x,y,z:longint):longint;
var q:longint;
begin
q:=lca(x,y);
exit(hash[query(,up,root[x],root[y],root[q],root[f[q,]],z)]);
end; procedure rebuild(u,pre:longint);
var e,v:longint;
begin
inc(top); stk[top]:=u;
update(,up,root[pre],root[u],a[u]);
dep[u]:=dep[pre]+;
f[u,]:=pre;
e:=head[u];
while e<> do
begin
v:=vet[e];
if v<>pre then rebuild(v,u);
e:=next[e];
end;
end; procedure merge(x,y:longint);
var tx,ty,z,i,j:longint;
begin
tx:=find(x); ty:=find(y);
if size[tx]>size[ty] then
begin
swap(tx,ty); swap(x,y);
end;
top:=;
add(x,y); add(y,x);
rebuild(x,y);
h[tx]:=ty; size[ty]:=size[ty]+size[tx];
for i:= to do
for j:= to top do
begin
z:=stk[j];
f[z,i]:=f[f[z,i-],i-];
end;
end; begin
assign(input,'bzoj3123.in'); reset(input);
assign(output,'bzoj3123.out'); rewrite(output);
readln(x);
readln(n,m,que);
for i:= to n do
begin
read(a[i]);
c[i]:=a[i];
end;
qsort(,n);
up:=; hash[]:=c[];
for i:= to n do
if c[i]<>c[i-] then begin inc(up); hash[up]:=c[i]; end;
for i:= to n do a[i]:=lsh(a[i]);
for i:= to m do
begin
readln(x,y);
add(x,y);
add(y,x);
end;
for i:= to n do
begin
h[i]:=i; size[i]:=;
end;
for i:= to n do
if root[i]= then dfs(i,);
for i:= to do
for j:= to n do f[j,i]:=f[f[j,i-],i-];
for i:= to que do
begin
readln(ch); s:=; k:=length(ch); x:=; y:=; z:=;
for j:= to k do
begin
if ch[j]=' ' then begin if ch[j-]<>' ' then inc(s); continue; end;
if s= then x:=x*+ord(ch[j])-ord('');
if s= then y:=y*+ord(ch[j])-ord('');
if s= then z:=z*+ord(ch[j])-ord('');
end;
if ch[]='Q' then
begin
x:=x xor lastans; y:=y xor lastans; z:=z xor lastans; //writeln(x,' ',y,' ',z);
k:=ask(x,y,z);
writeln(k);
lastans:=k;
end
else
begin
x:=x xor lastans; y:=y xor lastans;// writeln(x,' ',y,' ',z);
merge(x,y);
end; end;
close(input);
close(output);
end.

【BZOJ3123】森林(主席树,启发式合并)的更多相关文章

  1. 【BZOJ-3123】森林 主席树 + 启发式合并

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

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

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

  3. Bzoj 3123: [Sdoi2013]森林(主席树+启发式合并)

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

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

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

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

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

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

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

  7. [SDOI2013]森林 主席树+启发式合并

    这题的想法真的很妙啊. 看到题的第一眼,我先想到树链剖分,并把\(DFS\)序当成一段区间上主席树.但是会发现在询问的时候,可能会非常复杂,因为你需要把路径拆成很多条轻链和重链,它们还不一定连续,很难 ...

  8. 【BZOJ 3123】 [Sdoi2013]森林 主席树启发式合并

    我们直接按父子关系建主席树,然后记录倍增方便以后求LCA,同时用并查集维护根节点,而且还要记录根节点对应的size,用来对其启发式合并,然后每当我们合并的时候我们都要暴力拆小的一部分重复以上部分,总时 ...

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

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

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

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

随机推荐

  1. XE6 & IOS开发之开发者账号、苹果证书(1):关于开发者账号

    网上能找到的关于Delphi XE系列的移动开发的相关文章甚少,本文尽量以详细的图文内容.傻瓜式的表达来告诉你想要的答案. 原创作品,请尊重作者劳动成果,转载请注明出处!!! 关于苹果开发者账号, 注 ...

  2. 【转】Hibernate级联注解CascadeType参数详解

    cascade(级联) 级联在编写触发器时经常用到,触发器的作用是当 主控表信息改变时,用来保证其关联表中数据同步更新.若对触发器来修改或删除关联表相记录,必须要删除对应的关联表信息,否则,会存有脏数 ...

  3. ckeditor插件

    插件下载地址:http://ckeditor.com/download 1.CKeditor配置 在html页面的<head>标签中引入核心文件 ckeditor.js <scrip ...

  4. Android IOS WebRTC 音视频开发总结(八十六)-- WebRTC中RTP/RTCP协议实现分析

    本文主要介绍WebRTC中的RTP/RTCP协议,作者:weizhenwei ,文章最早发表在编风网,微信ID:befoio 支持原创,转载必须注明出处,欢迎关注我的微信公众号blacker(微信ID ...

  5. Eclipses使用小技巧

    1.新导入Eclipse的项目,显示很多错误,一般是因为没有加上对应的Lib,添加后错误消失. 2.如果还有错误,而且是与JavaEE相关的,比如说HttpServlet类找不到,更新一下tomcat ...

  6. <读书笔记>软件调试之道 :问题的核心-诊断

    声明:本文档的内容主要来源于书籍<软件调试修炼之道>作者Paul Butcher,属于读书笔记. 不要急于动手! 尽管可以利用各种工具和技术以及软件自身查找缺陷,但是你最重要的财富是你的智 ...

  7. 关键字extern

    extern 可以置于  变量  或  函数  前,  以表明变量 或 函数 的定义在别的文件中,  下面代码用到的这些变量  或 函数是外来的,  不是本文件定义的, 提示链接器遇到此变量和函数时在 ...

  8. JS学习知我见(常用建站代码)

    <!doctype html><html><head><meta charset="utf-8"><meta name=&qu ...

  9. java中获取接口(方法)中的参数名字(eclipse设置编译参数)(java8 javac -parameters)

    interface接口参数 jdk1.7及以前使用spring功能实现的: 注意: 1.该功能只能获取类的方法的参数名,不能获取接口的方法的参数名. public static void test() ...

  10. jQuery 正则选择器

    http://james.padolsey.com/snippets/regex-selector-for-jquery/ A while ago I published an article exp ...