[BZOJ 3551+3545]Peaks
加强:题目传送-BZOJ3551
原味:题目传送-BZOJ3545
题意:
有一个\(n\)个点\(m\)条边的无向图,点有点权,边有边权。
有\(q\)次询问(u,val,k)
表示从\(u\)出发,经过的边权都小于等于\(val\),能到达的所有点中,点权第\(k\)大的权值
强制在线
$n \le 100000,m \le 500000,q \le 300000 $
题解:
做过NOI2018D1T1的再做这题就思路清晰了
你需要先学会Kruskal重构树,也不是什么高大上的东西..
然后这就变成了一棵树,按DFS序将叶子节点映射到一个序列上
转换为区间第K大,就随便做了..我用的是主席树
过程:
先忘了强制在线,再各种细节..
代码:
const int N=100010,M=500010,lgN=18,ALL=N<<1;
int n,m,q,rt,all;
int h[N];
int head[ALL],nxt[ALL],to[ALL],lst=0;
int bd[ALL],fa[ALL];
inline void adde(int x,int y) {
assert(fa[y]==x);
nxt[++lst]=head[x]; to[lst]=y; head[x]=lst;
}
namespace KRU {
struct EDGE {
int x,y,c;
inline void in() {
read(x); read(y); read(c);
}
bool operator < (const EDGE &a)const {
return c<a.c;
}
}e[M];
int fat[N],ref[N],ind=0;
int father(int x) {return x==fat[x] ? x : fat[x]=father(fat[x]);}
inline int Kruskal() {
sort(e+1,e+m+1); int k=0; ind=n;
for(int i=1;i<=n;i++) fat[i]=ref[i]=i;
for(int i=1;i<=m;i++) {
int fx=father(e[i].x),fy=father(e[i].y);
if(fx!=fy) {
int np=++ind; fa[ref[fy]]=fa[ref[fx]]=np;
adde(np,ref[fy]); adde(np,ref[fx]); bd[np]=e[i].c;
ref[fy]=np; ref[fx]=0; fat[fx]=fy;
if(++k==n-1) return ind;
}
}
int np=++ind; bd[np]=INF;
for(int i=1;i<=n;i++)
if(father(i)==i) {
fa[ref[i]]=np;
adde(np,ref[i]);
}
// printf("lst=%d\n",lst);
return ind;
}
}
int le[ALL],t_s[ALL],s_t[ALL],ind=0;
namespace TREE {
int anc[ALL][lgN+2],lim[ALL][lgN+2],dep[ALL],sz[ALL];
void Print(int u) {
for(int i=1;i<dep[u];i++) putchar('\t'); printf("%d:%d %d\n",u,fa[u],bd[u]);
for(int i=head[u];i;i=nxt[i]) Print(to[i]);
}
int cnt;
void Build(int u) {
// printf("%d\n",u);
bool fl=0; sz[u]=0; ++cnt;
for(int i=head[u];i;i=nxt[i]) {
int v=to[i]; assert(v!=fa[u]);
dep[v]=dep[u]+1;
anc[v][0]=u;
lim[v][0]=bd[u];
Build(v);
if(!fl) le[u]=le[v];
sz[u]+=sz[v];
fl=1;
}
if(!fl) assert(u<=n);
if(u<=n) assert(!fl);
if(!fl) {le[u]=u; t_s[u]=++ind; s_t[ind]=u; sz[u]=1;}
}
inline void Init(int rt) {
lim[rt][0]=INF; dep[rt]=1;//ATT
mem(lim,63);
Build(rt); assert(cnt==all); assert(ind==n);
for(int j=1;j<=lgN;j++)
for(int i=1;i<=all;i++) {
anc[i][j]=anc[anc[i][j-1]][j-1];
lim[i][j]=lim[anc[i][j-1]][j-1];
}
}
inline int Find(int u,int v) {
for(int i=lgN;i>=0;i--) if(lim[u][i]<=v) u=anc[u][i];
return u;
}
}
namespace SEG {
#define lc ch[u][0]
#define rc ch[u][1]
#define left lc,l,mid
#define right rc,mid+1,r
#define mid ((l+r)>>1)
const int U=N*lgN;
int rt[ALL],sz[U],ch[U][2],ind=1;
inline int New_Node(int u) {
sz[++ind]=sz[u];
ch[ind][0]=ch[u][0]; ch[ind][1]=ch[u][1];
return ind;
}
void Modify(int &u,int l,int r,int x) {
// printf("%d %d %d %d\n",u,l,r,x);
u=New_Node(u);
if(l==r) {
if(l!=x) cerr<<x<<endl;
assert(l==x);
++sz[u]; return;
}
if(x<=mid) Modify(left,x);
if(x> mid) Modify(right,x);
sz[u]=sz[lc]+sz[rc];
}
int Query(int u1,int u2,int l,int r,int k) {
if(l==r) return l;
int szl=sz[ch[u2][0]]-sz[ch[u1][0]];
// printf("%d %d %d %d %d\n",u1,u2,szl,l,r);
if(szl<k) return Query(ch[u1][1],ch[u2][1],mid+1,r,k-szl);
else return Query(ch[u1][0],ch[u2][0],l,mid,k);
}
inline void Init() {
for(int i=1;i<=n;i++) {
rt[i]=rt[i-1];
// printf("%d\n",s_t[i]);
Modify(rt[i],1,n,h[s_t[i]]);
// printf("%d\n",sz[rt[i]]);
}
// printf("rt\n"); for(int i=1;i<=n;i++) printf("%d ",rt[i]); puts("");
}
}
map<int,int> key;
int _key[N];
int num[N],tot;
signed main() {
// freopen("4.in","r",stdin);
// freopen("my.out","w",stdout);
read(n); read(m); read(q); tot=n;
for(int i=1;i<=n;i++) read(h[i]),num[i]=h[i];
sort(num+1,num+n+1); tot=unique(num+1,num+tot+1)-num-1;
for(int i=tot;i>=1;i--) key[num[i]]=tot-i+1,_key[tot-i+1]=num[i];//reverse
for(int i=1;i<=n;i++) h[i]=key[h[i]],assert(h[i]!=0);
for(int i=1;i<=m;i++) KRU::e[i].in();
all=rt=KRU::Kruskal(); TREE::Init(rt); SEG::Init();
int ans=0;
while(q--) {
int u,v,k; read(u); read(v); read(k);
u^=ans; v^=ans; k^=ans;
u=TREE::Find(u,v);
// cerr<<'u'<<u<<"BD::"<<TREE::lim[u][0]<<" "<<v<<endl;
if(TREE::sz[u]<k) ans=0,puts("-1");
else {
ans=SEG::Query(SEG::rt[t_s[le[u]]-1],SEG::rt[t_s[le[u]]+TREE::sz[u]-1],1,n,k);
printf("%d\n",ans=_key[ans]);
}
}
return 0;
}
/*
10 11 4
1 2 3 4 5 6 7 8 9 10
1 4 4
2 5 3
9 8 2
7 8 10
7 1 4
6 7 1
6 4 8
2 1 5
10 8 10
3 4 7
3 4 6
1 5 2
1 5 6
1 5 8
8 9 2
*/
用时:1.5h