bzoj 3551 kruskal重构树dfs序上的主席树
2017-08-05 08:36
288 查看
强制在线
kruskal重构树,每两点间的最大边权即为其lca的点权。
倍增找,dfs序对应区间搞主席树
#include<cstdio>
#include<cstring>
#include<iostream>
#include<cmath>
#include<algorithm>
#define N 100005
#define M 500005
using namespace std;
int l[2*N],r[2*N],cnt,num_cnt,val[2*N],num[2*N],ans;
int sum[25*N],lon[25*N],ron[25*N];
int be[2*N],fa[2*N][21],dis[2*N][21],n,m,q,sz,oo,root[2*N];
int e=1,head[2*N];
bool vis[2*N];
struct edge{
int u,v,w,next;
}ed[M],a[M];
bool cmp1(edge a,edge b){return a.w<b.w;}
void add(int u,int v,int w){
ed[e].u=u; ed[e].v=v; ed[e].w=w;
ed[e].next=head[u]; head[u]=e++;
}
int find(int x){
if(x==be[x])return x;
be[x]=find(be[x]);
return be[x];
}
void Kruskal(){
sort(a+1,a+m+1,cmp1);
for(int i=1;i<=m;++i){
int u=a[i].u,v=a[i].v;
u=find(u); v=find(v);
if(u!=v){
be[u]=be[v]=++n;
fa[u][0]=fa[v][0]=n;
dis[u][0]=dis[v][0]=a[i].w;
add(n,u,a[i].w); add(n,v,a[i].w);
}
}
}
void insert(int p,int &rt,int l,int r,int x){
rt=++sz;
sum[rt]=sum[p]+1;
if(l==r) return;
lon[rt]=lon[p]; ron[rt]=ron[p];
int mid=(l+r)>>1;
if(x<=mid) insert(lon[p],lon[rt],l,mid,x);
else insert(ron[p],ron[rt],mid+1,r,x);
}
void dfs(int x){
for(int i=1;i<=20;i++){
fa[x][i]=fa[fa[x][i-1]][i-1];
dis[x][i]=max(dis[x][i-1],dis[fa[x][i-1]][i-1]);
}
l[x]=++cnt;
if(x<=oo) insert(root[cnt-1],root[cnt],1,num_cnt,val[x]);
else root[cnt]=root[cnt-1];
for(int i=head[x];i;i=ed[i].next)
dfs(ed[i].v);
r[x]=cnt;
}
int query(int L,int R,int k){
L=root[L]; R=root[R];
if(k>sum[R]-sum[L]) return -1;
int x=1,y=num_cnt;
while(x<y){
int mid=(x+y)>>1;
int tmp=sum[ron[R]]-sum[ron[L]];
if(tmp>=k){x=mid+1;L=ron[L];R=ron[R];}
else{k-=tmp;y=mid;L=lon[L];R=lon[R];}
}
return num[x];
}
void print(int x,int l,int r){
if(!x) return;
printf("x==%d l==%d r==%d sum==%d\n",x,l,r,sum[x]);
int mid=(l+r)>>1;
print(lon[x],l,mid);
print(ron[x],mid+1,r);
}
int main()
{
//freopen("3545.in","r",stdin);
//freopen("3545.out","w",stdout);
int u,v,w,x,k;
scanf("%d%d%d",&n,&m,&q); oo=n;
for(int i=1;i<=n;i++){
scanf("%d",&val[i]);
num[i]=val[i];
}
sort(num+1,num+n+1);
num_cnt=unique(num+1,num+n+1)-num-1;
for(int i=1;i<=n;i++)
val[i]=lower_bound(num+1,num+num_cnt+1,val[i])-num;
for(int i=1;i<=m;i++)
scanf("%d%d%d",&a[i].u,&a[i].v,&a[i].w);
for(int i=1;i<=2*n;++i)be[i]=i;
Kruskal();
memset(vis,0,sizeof vis);
for(int i=n;i>=1;--i)if(!l[i])dfs(i);
while(q--){
scanf("%d%d%d",&v,&x,&k);
if(ans!=-1){v^=ans;x^=ans;k^=ans;}
for(int i=20;~i;i--)
if(dis[v][i]<=x&&fa[v][i])
v=fa[v][i];
ans=query(l[v]-1,r[v],k);
printf("%d\n",ans);
}
return 0;
}
kruskal重构树,每两点间的最大边权即为其lca的点权。
倍增找,dfs序对应区间搞主席树
#include<cstdio>
#include<cstring>
#include<iostream>
#include<cmath>
#include<algorithm>
#define N 100005
#define M 500005
using namespace std;
int l[2*N],r[2*N],cnt,num_cnt,val[2*N],num[2*N],ans;
int sum[25*N],lon[25*N],ron[25*N];
int be[2*N],fa[2*N][21],dis[2*N][21],n,m,q,sz,oo,root[2*N];
int e=1,head[2*N];
bool vis[2*N];
struct edge{
int u,v,w,next;
}ed[M],a[M];
bool cmp1(edge a,edge b){return a.w<b.w;}
void add(int u,int v,int w){
ed[e].u=u; ed[e].v=v; ed[e].w=w;
ed[e].next=head[u]; head[u]=e++;
}
int find(int x){
if(x==be[x])return x;
be[x]=find(be[x]);
return be[x];
}
void Kruskal(){
sort(a+1,a+m+1,cmp1);
for(int i=1;i<=m;++i){
int u=a[i].u,v=a[i].v;
u=find(u); v=find(v);
if(u!=v){
be[u]=be[v]=++n;
fa[u][0]=fa[v][0]=n;
dis[u][0]=dis[v][0]=a[i].w;
add(n,u,a[i].w); add(n,v,a[i].w);
}
}
}
void insert(int p,int &rt,int l,int r,int x){
rt=++sz;
sum[rt]=sum[p]+1;
if(l==r) return;
lon[rt]=lon[p]; ron[rt]=ron[p];
int mid=(l+r)>>1;
if(x<=mid) insert(lon[p],lon[rt],l,mid,x);
else insert(ron[p],ron[rt],mid+1,r,x);
}
void dfs(int x){
for(int i=1;i<=20;i++){
fa[x][i]=fa[fa[x][i-1]][i-1];
dis[x][i]=max(dis[x][i-1],dis[fa[x][i-1]][i-1]);
}
l[x]=++cnt;
if(x<=oo) insert(root[cnt-1],root[cnt],1,num_cnt,val[x]);
else root[cnt]=root[cnt-1];
for(int i=head[x];i;i=ed[i].next)
dfs(ed[i].v);
r[x]=cnt;
}
int query(int L,int R,int k){
L=root[L]; R=root[R];
if(k>sum[R]-sum[L]) return -1;
int x=1,y=num_cnt;
while(x<y){
int mid=(x+y)>>1;
int tmp=sum[ron[R]]-sum[ron[L]];
if(tmp>=k){x=mid+1;L=ron[L];R=ron[R];}
else{k-=tmp;y=mid;L=lon[L];R=lon[R];}
}
return num[x];
}
void print(int x,int l,int r){
if(!x) return;
printf("x==%d l==%d r==%d sum==%d\n",x,l,r,sum[x]);
int mid=(l+r)>>1;
print(lon[x],l,mid);
print(ron[x],mid+1,r);
}
int main()
{
//freopen("3545.in","r",stdin);
//freopen("3545.out","w",stdout);
int u,v,w,x,k;
scanf("%d%d%d",&n,&m,&q); oo=n;
for(int i=1;i<=n;i++){
scanf("%d",&val[i]);
num[i]=val[i];
}
sort(num+1,num+n+1);
num_cnt=unique(num+1,num+n+1)-num-1;
for(int i=1;i<=n;i++)
val[i]=lower_bound(num+1,num+num_cnt+1,val[i])-num;
for(int i=1;i<=m;i++)
scanf("%d%d%d",&a[i].u,&a[i].v,&a[i].w);
for(int i=1;i<=2*n;++i)be[i]=i;
Kruskal();
memset(vis,0,sizeof vis);
for(int i=n;i>=1;--i)if(!l[i])dfs(i);
while(q--){
scanf("%d%d%d",&v,&x,&k);
if(ans!=-1){v^=ans;x^=ans;k^=ans;}
for(int i=20;~i;i--)
if(dis[v][i]<=x&&fa[v][i])
v=fa[v][i];
ans=query(l[v]-1,r[v],k);
printf("%d\n",ans);
}
return 0;
}
相关文章推荐
- BZOJ 3551: [ONTAK2010]Peaks加强版 [Kruskal重构树 dfs序 主席树]
- 【BZOJ-3545&3551】Peaks&加强版 Kruskal重构树 + 主席树 + DFS序 + 倍增
- bzoj 3551 kruskal重构树dfs序上的主席树
- [bzoj3545+3551][ONTAK2010]Peaks&&加强版(离线+线段树合并)||(kruskal重构树&&dfs序+主席树)
- [BZOJ3551][ONTAK2010]Peaks(加强版)(Kruskal重构树,主席树)
- bzoj3551 [ONTAK2010]Peaks加强版(Kruskal重构树+主席树)
- bzoj 3551 [ONTAK2010]Peaks加强版(kruskal,主席树,dfs序)
- bzoj 3551: [ONTAK2010]Peaks加强版 Kruskal重构树+可持久化线段树
- bzoj3551 [ONTAK2010]Peaks加强版(kruskal重构树+dfs序+主席树+树上倍增)
- BZOJ 3551 ONTAK2010 Peaks加强版 Kruskal重构树+可持久化线段树
- bzoj3545&&3551: [ONTAK2010]Peaks离线&&在线【线段树合并&&kruskal重构树&&主席树】
- 【BZOJ 3545】【ONTAK 2010】Peaks & 【BZOJ 3551】【ONTAK 2010】Peaks加强版 Kruskal重构树
- BZOJ 3551 ONTAK2010 Peaks加强版 Kruskal重构树+可持久化线段树
- 【BZOJ3551】[ONTAK2010]Peaks加强版 最小生成树+DFS序+主席树
- 【BZOJ 3551】[ONTAK2010] Peaks加强版 Kruskal重构树+树上倍增+主席树
- [省选前题目整理][BZOJ 2588][SPOJ COT]Count On a Tree(DFS序主席树)
- 【BZOJ3653】谈笑风生【主席树】【DFS序】
- [bzoj3123][sdoi2013森林] (树上主席树+lca+并查集启发式合并+暴力重构森林)
- 3551 [ONTAK2010]Peaks加强版 kruskal重构树 可持久化线段树
- 【kruskal】【dfs】【JSOI 2008】【bzoj 1016】最小生成树计数