【BZOJ 3551】Peaks加強版
阿新 • • 發佈:2018-12-18
題目描述
在 Bytemountains 有 座山峰,每座山峰有他的高度 。有些山峰之間有雙向道路相連,共 條路徑,每條路徑有一個困難值,這個值越大表示越難走,現在有 組詢問,每組詢問詢問從點 開始只經過困難值小於等於 的路徑所能到達的山峰中第 高的山峰,如果無解輸出 。,,。
演算法分析
學習了一下 Kruskal 重構樹,本題利用了 Kruskal 重構樹的堆性質,只需要樹上倍增找到能走到的最接近根節點的祖先,所有能到達的山峰就是其所在子樹的所有葉子節點,可以用 DFS 序+主席樹維護子樹中的葉子節點權值。
細節有主席樹求區間第 小而本題要求區間第 大,需要簡單轉化一下,還有注意維護的是子樹中葉子節點的權值。
【BZOJ 3545】Peaks 為不強制線上的版本,雙倍經驗哦。
程式碼實現
#include <cstdio>
#include <algorithm>
const int maxn=(int)1e5+5;
const int maxm=(int)5e5+5;
char buf[1<<15],*fs=buf,*ft=buf;
inline char gc() {
if(fs==ft) {
ft=(fs=buf) +fread(buf,1,1<<15,stdin);
if(fs==ft) return 0;
}
return *fs++;
}
inline void read(int &num) {
char c=gc();int f=false;num=0;
while(c<'0'||'9'<c) {if(c=='-') f=true;c=gc();}
while('0'<=c&&c<='9') {num=num*10+c-'0';c=gc();}
if(f) num=-num;
}
int sum[maxn<<6],lch[maxn<<6],rch[maxn<<6],cnt=0;
int ins(int o,int l,int r,int x) {
int mid=(l+r)>>1,nxt=++cnt;
if(l==r) sum[nxt]=sum[o]+1;
else {
lch[nxt]=(x<=mid)?ins(lch[o],l,mid,x):lch[o];
rch[nxt]=(mid+1<=x)?ins(rch[o],mid+1,r,x):rch[o];
sum[nxt]=sum[lch[nxt]]+sum[rch[nxt]];
}
return nxt;
}
int query(int x,int y,int l,int r,int k) {
int mid=(l+r)>>1;if(l==r) return mid;
int lcnt=sum[lch[y]]-sum[lch[x]];
if(k<=lcnt) return query(lch[x],lch[y],l,mid,k);
return query(rch[x],rch[y],mid+1,r,k-lcnt);
}
struct edge {int u,v,w;} e[maxm];
inline bool cmp(const edge &x,const edge &y) {return x.w<y.w;}
int head[maxn<<1],ev[maxn<<1],nxt[maxn<<1],idx=0;
inline void add(int u,int v) {ev[++idx]=v;nxt[idx]=head[u];head[u]=idx;}
int fa[maxn<<1];int find(int x) {return x==fa[x]?x:fa[x]=find(fa[x]);}
int ha[maxn],sz=0;inline int ask(int x) {return std::lower_bound(ha,ha+sz,x)-ha+1;}
int h[maxn<<1],pa[maxn<<1][20],rt[maxn<<1],tot[maxn<<1],dl[maxn<<1],dfn[maxn<<1],dfsidx=0;
void dfs(int x,int fa) {
dl[dfn[x]=++dfsidx]=x;tot[x]=1;
for(register int i=head[x];i;i=nxt[i]) {
int v=ev[i];dfs(v,x);tot[x]+=tot[v];
}
}
int main() {
int ln,n,m,q;read(n);ln=n;read(m);read(q);
for(register int i=1;i<=n;++i) {read(h[i]);ha[i-1]=h[i];}
std::sort(ha,ha+n);sz=std::unique(ha,ha+n)-ha;
for(register int i=0;i<m;++i) {read(e[i].u);read(e[i].v);read(e[i].w);}
std::sort(e,e+m,cmp);
for(register int i=1;i<=(n<<1);++i) fa[i]=i;
for(register int i=0;i<m;++i) {
int x=find(e[i].u),y=find(e[i].v);if(x==y) continue;
++n;h[n]=e[i].w;pa[x][0]=pa[y][0]=fa[x]=fa[y]=n;add(n,x);add(n,y);
}
for(register int i=1;i<20;++i) for(register int x=1;x<=n;++x) pa[x][i]=pa[pa[x][i-1]][i-1];
dfs(n,0);for(register int i=1;i<=n;++i) rt[i]=(dl[i]<=ln)?ins(rt[i-1],1,sz,ask(h[dl[i]])):rt[i-1];
int v,x,k,la=0;
while(q--) {
read(v);read(x);read(k);if(~la) {v^=la;x^=la;k^=la;}
for(int i=19;i>=0;--i) if(pa[v][i]&&h[pa[v][i]]<=x) v=pa[v][i];
int l=dfn[v],r=dfn[v]+tot[v]-1,cnt=sum[rt[r]]-sum[rt[l-1]];
printf("%d\n",la=(k<=cnt?ha[query(rt[l-1],rt[r],1,sz,cnt+1-k)-1]:-1));
}
return 0;
}