3551 [ONTAK2010]Peaks加强版 kruskal重构树 可持久化线段树
2017-01-06 19:32
369 查看
名字是大爷起的。
不过这个东西好像确实很厉害的样子。。
一开始在想一个可持久化并查集+线段树合并+可持久化线段树维护根的做法。不过看到128M的内存果断选亡。。。
设最初的所有点点权为0.
在kruskal的时候,每加一条边时新加一个点,两个并查集的根并到这个点上,这个点的点权是这条边的边权。
然后这个东西构成了一个堆式的结构,父节点的点权大于儿子的点权。
并且叶节点是最初的点。
两个点间路径的最大边权是在这个东西上两个点lca的点权。
求的时候倍增找到深度最小的点权大于等于询问权值的点。
然后这个点子树中的最初点是满足条件的点。
求一个dfs序,用可持久化线段树维护区间K大值。
不过这个东西好像确实很厉害的样子。。
一开始在想一个可持久化并查集+线段树合并+可持久化线段树维护根的做法。不过看到128M的内存果断选亡。。。
设最初的所有点点权为0.
在kruskal的时候,每加一条边时新加一个点,两个并查集的根并到这个点上,这个点的点权是这条边的边权。
然后这个东西构成了一个堆式的结构,父节点的点权大于儿子的点权。
并且叶节点是最初的点。
两个点间路径的最大边权是在这个东西上两个点lca的点权。
求的时候倍增找到深度最小的点权大于等于询问权值的点。
然后这个点子树中的最初点是满足条件的点。
求一个dfs序,用可持久化线段树维护区间K大值。
#include <bits/stdc++.h> using namespace std; #define N1 210000 #define N 510000 #define M 7000000 int n,m,Q,tot,cnt,rt,num,ans; int h ,h1 ,a ,b ,c ,pos ,v ,root ; int son [2],fa[N1][21],beg ,ed ,bel ,ft ; int ch[M][2],size[M]; int cmp(int x,int y){return c[x]<c[y];} int find(int x){return ft[x]==x ? x:ft[x]=find(ft[x]);} void build(int l,int r,int &now,int pre,int pos) { now=++cnt; size[now]=size[pre]+1; if(l==r)return; ch[now][0]=ch[pre][0]; ch[now][1]=ch[pre][1]; int mid=(l+r)>>1; if(mid>=pos)build(l,mid,ch[now][0],ch[pre][0],pos); else build(mid+1,r,ch[now][1],ch[pre][1],pos); } void dfs(int x) { for(int i=1;i<=20;i++) fa[x][i]=fa[fa[x][i-1]][i-1]; if(x<=n) { beg[x]=ed[x]=++num; build(1,n,root[num],root[num-1],h[x]); return; } dfs(son[x][0]);dfs(son[x][1]); beg[x]=beg[son[x][0]]; ed[x]=ed[son[x][1]]; } int get(int x,int val) { for(int i=20;i>=0;i--) if(fa[x][i]&&v[fa[x][i]]<=val) x=fa[x][i]; return x; } int query(int l,int r,int now,int pre,int K) { if(l==r)return h1[l]; int t=size[ch[now][1]]-size[ch[pre][1]],mid=(l+r)>>1; if(t>=K)return query(mid+1,r,ch[now][1],ch[pre][1],K); else return query(l,mid,ch[now][0],ch[pre][0],K-t); } int main() { //freopen("tt.in","r",stdin); scanf("%d%d%d",&n,&m,&Q); for(int i=1;i<=n;i++) scanf("%d",&h[i]),h1[i]=h[i]; sort(h1+1,h1+1+n); for(int i=1;i<=n;i++) h[i]=lower_bound(h1+1,h1+1+n,h[i])-h1; for(int i=1;i<=m;i++) scanf("%d%d%d",&a[i],&b[i],&c[i]),pos[i]=i; sort(pos+1,pos+1+m,cmp); for(int i=1;i<=n*2;i++)ft[i]=i; tot=n; for(int i=1,t;i<=m;i++) { int x=find(a[t=pos[i]]),y=find(b[t]); if(x==y)continue; fa[x][0]=fa[y][0]=++tot; ft[x]=ft[y]=tot; son[tot][0]=x;son[tot][1]=y; v[tot]=c[t]; } dfs(rt=find(1)); for(int v,x,K;Q--;) { scanf("%d%d%d",&v,&x,&K); //if(ans!=-1)v^=ans,x^=ans,K^=ans; int t=get(v,x); if(ed[t]-beg[t]+1<K)ans=-1; else ans=query(1,n,root[ed[t]],root[beg[t]-1],K); printf("%d\n",ans); } return 0; }
相关文章推荐
- BZOJ 3551 ONTAK2010 Peaks加强版 Kruskal重构树+可持久化线段树
- BZOJ 3551 ONTAK2010 Peaks加强版 Kruskal重构树+可持久化线段树
- bzoj 3551: [ONTAK2010]Peaks加强版 Kruskal重构树+可持久化线段树
- bzoj3551 [ONTAK2010]Peaks加强版(Kruskal重构树+主席树)
- 【BZOJ 3545】【ONTAK 2010】Peaks & 【BZOJ 3551】【ONTAK 2010】Peaks加强版 Kruskal重构树
- BZOJ 3551: [ONTAK2010]Peaks加强版 [Kruskal重构树 dfs序 主席树]
- [BZOJ3551][ONTAK2010]Peaks(加强版)(Kruskal重构树,主席树)
- [bzoj3545+3551][ONTAK2010]Peaks&&加强版(离线+线段树合并)||(kruskal重构树&&dfs序+主席树)
- 3551: [ONTAK2010]Peaks加强版 kruskal重构树+dfs序+主席树
- bzoj3551 [ONTAK2010]Peaks加强版(kruskal重构树+dfs序+主席树+树上倍增)
- 【BZOJ 3551】[ONTAK2010] Peaks加强版 Kruskal重构树+树上倍增+主席树
- bzoj 3551 [ONTAK2010]Peaks加强版(kruskal,主席树,dfs序)
- 【BZOJ-3545&3551】Peaks&加强版 Kruskal重构树 + 主席树 + DFS序 + 倍增
- bzoj3545&&3551: [ONTAK2010]Peaks离线&&在线【线段树合并&&kruskal重构树&&主席树】
- 【ONTAK2010】【BZOJ3551】Peaks加强版
- BZOJ3551 [ONTAK2010]Peaks加强版
- [BZOJ3551][ONTAK2010]Peaks加强版
- [BZOJ3551][ONTAK2010]Peaks加强版
- 【bzoj3551】【ONTAK2010】【peaks加强版】【主席树】
- BZOJ3551: [ONTAK2010]Peaks加强版