[BZOJ3551][ONTAK2010]Peaks(加强版)(Kruskal重构树,主席树)
2018-04-18 18:51
387 查看
3551: [ONTAK2010]Peaks加强版
Time Limit: 20 Sec Memory Limit: 128 MB
Submit: 2438 Solved: 763
[Submit][Status][Discuss]Description
【题目描述】同3545Input
第一行三个数N,M,Q。 第二行N个数,第i个数为h_i 接下来M行,每行3个数a b c,表示从a到b有一条困难值为c的双向路径。 接下来Q行,每行三个数v x k,表示一组询问。v=v xor lastans,x=x xor lastans,k=k xor lastans。如果lastans=-1则不变。Output
同3545Sample Input
Sample Output
HINT
【数据范围】同3545Source
[Submit][Status][Discuss]
做一遍Kruskal,每次加入一条边的时候为这条边新建一个点,点权为其边权,分别连向两个连通块。就建出了一个Kruskal重构树。
重构树的性质:是一个二叉堆,且原图中两点的满足“路径上最大边权最小”的路径的最大边权就是新树中两点的LCA的点权。
建出来求出DFS序跑主席树即可。
接下来吐槽这道题。题目是3545的加强版,加了强制在线不给样例,结果拿原题的样例死活测不对。导致我对着一个正确的程序调了整整一个下午。
#include<cstdio> #include<algorithm> #define rep(i,l,r) for (int i=l; i<=r; i++) using namespace std; const int N=200100,M=6000100; int n,m,Q,x,ans,val ,tot,u,lim,k,tim,cnt,nd,dep ,dfn ,L ,R ,ls[M],rs[M],sz[M]; int fa [20],mp ,f ,to[N<<1],nxt[N<<1],h ,root ; struct P{ int u,v,w; bool operator <(const P &r)const{ return w<r.w; }}a[500100]; int find(int x){ return (x==f[x]) ? x : f[x]=find(f[x]); } void add(int u,int v){ to[++cnt]=v; nxt[cnt]=h[u]; h[u]=cnt; } void Kruskal(){ sort(a+1,a+m+1); int k=0; rep(i,1,m){ int u=a[i].u,v=a[i].v,w=a[i].w,x=find(u),y=find(v); if (x==y) continue; val[++tot]=w; add(tot,x); add(tot,y); f[x]=f[y]=f[tot]=tot; if (++k==n-1) break; } } void dfs(int u){ if (u<=n) dfn[++tim]=u; L[u]=tim; for (int i=1; (1<<i)<=dep[u]; i++) fa[u][i]=fa[fa[u][i-1]][i-1]; for (int i=h[u],k; i; i=nxt[i]) if ((k=to[i])!=fa[u][0]) fa[k][0]=u,dep[k]=dep[u]+1,dfs(k); R[u]=tim; } void insert(int y,int &x,int L,int R,int pos){ ls[x=++nd]=ls[y]; rs[x]=rs[y]; sz[x]=sz[y]+1; if (L==R) return; int mid=(L+R)>>1; if (pos<=mid) insert(ls[y],ls[x],L,mid,pos); else insert(rs[y],rs[x],mid+1,R,pos); } int que(int x,int y,int k){ x=root[x]; y=root[y]; int all=sz[y]-sz[x]; if (k>all) return -1; k=all-k+1; int L=1,R=*mp; while (L!=R){ int S=sz[ls[y]]-sz[ls[x]],mid=(L+R)>>1; if (k<=S) x=ls[x],y=ls[y],R=mid; else x=rs[x],y=rs[y],L=mid+1,k-=S; } return L; } int main(){ freopen("bzoj3551.in","r",stdin); freopen("bzoj3551.out","w",stdout); scanf("%d%d%d",&n,&m,&Q); tot=n; rep(i,1,n) scanf("%d",&x),val[i]=mp[i]=x,f[i]=i; val[0]=1e9+5; rep(i,1,m) scanf("%d%d%d",&a[i].u,&a[i].v,&a[i].w); Kruskal(); dfs(tot); sort(mp+1,mp+n+1); mp[0]=unique(mp+1,mp+n+1)-mp-1; rep(i,1,n) val[i]=lower_bound(mp+1,mp+mp[0]+1,val[i])-mp; rep(i,1,n) insert(root[i-1],root[i],1,*mp,val[dfn[i]]); rep(i,1,Q){ if (ans==-1) ans=0; scanf("%d%d%d",&u,&lim,&k); u^=ans; lim^=ans; k^=ans; for (int i=16; ~i; i--) if (val[fa[u][i]]<=lim) u=fa[u][i]; ans=que(L[u],R[u],k); if (~ans) ans=mp[ans]; printf("%d\n",ans); } return 0; }
相关文章推荐
- BZOJ 3551: [ONTAK2010]Peaks加强版 [Kruskal重构树 dfs序 主席树]
- bzoj3551 [ONTAK2010]Peaks加强版(Kruskal重构树+主席树)
- 【BZOJ 3545】【ONTAK 2010】Peaks & 【BZOJ 3551】【ONTAK 2010】Peaks加强版 Kruskal重构树
- bzoj3551 [ONTAK2010]Peaks加强版(kruskal重构树+dfs序+主席树+树上倍增)
- [bzoj3545+3551][ONTAK2010]Peaks&&加强版(离线+线段树合并)||(kruskal重构树&&dfs序+主席树)
- BZOJ 3551 ONTAK2010 Peaks加强版 Kruskal重构树+可持久化线段树
- BZOJ 3551 ONTAK2010 Peaks加强版 Kruskal重构树+可持久化线段树
- bzoj 3551: [ONTAK2010]Peaks加强版 Kruskal重构树+可持久化线段树
- 【BZOJ 3551】[ONTAK2010] Peaks加强版 Kruskal重构树+树上倍增+主席树
- bzoj 3551 [ONTAK2010]Peaks加强版(kruskal,主席树,dfs序)
- 【BZOJ-3545&3551】Peaks&加强版 Kruskal重构树 + 主席树 + DFS序 + 倍增
- 【bzoj3551】【ONTAK2010】【peaks加强版】【主席树】
- bzoj 3545&&3551: [ONTAK2010]Peaks &&加强版 平衡树&&并查集合并树&&主席树
- 【BZOJ3551】[ONTAK2010]Peaks加强版 最小生成树+DFS序+主席树
- [主席树 Kruscal] BZOJ 3545 [ONTAK2010]Peaks & 3551 [ONTAK2010]Peaks加强版
- 3551 [ONTAK2010]Peaks加强版 kruskal重构树 可持久化线段树
- 3551: [ONTAK2010]Peaks加强版 kruskal重构树+dfs序+主席树
- bzoj 3545/3551: [ONTAK2010]Peaks -- 主席树,最小生成树,倍增
- [BZOJ3551][ONTAK2010]Peaks加强版
- BZOJ3551 [ONTAK2010]Peaks加强版