题意:
给你一棵个点的树和
条路径,每条路径都有一个权值
。
有k组询问,每次询问给你一条路径和一个值。
问你被这条路径包含的所有路径中的第K小的路径的值
题解:
我用的是树上莫队+平衡树(或分块)的方法
平衡树的话是,分块的话就是
稍微口胡一下树上莫队:
把一颗树的欧拉序搞出来,对于查询的两点(假设
入栈早)。
如果是一条链,
否则,,同时莫队是要加入
平衡树有什么用?
我们看到题目中求第K大的值,就想到了用平衡树来维护值。
因为平衡树支持插入,删除和查找K大值,和莫队很配。
但其实分块更加优,分块能更好的和莫队配合。
因为分块的插入,
查询,总的复杂度是
(n,m同阶)
现在要处理的就是如何判断一条路径被包含,或者不被包含。
我们把每条路径看成两个点,如果这两个点都被包含,那么这条路径就是被包含的。
我们只要在莫队时记录一下每条路径两个端点被包含的个数即可。
由于同一个点可能是多条路径的端点,所以我们对每个点建一个vector,
我口胡一下分块的做法,因为更优(我一开始没想到)
先离散化,原来把值x插入平衡树(求第K大),现在就插入值域分块,
查询第K大,分块可以求出。
直接扫每一个块,扫到第一个 个数>=K的那个块停下来,再在块内暴力找。
代码:
(平衡树)
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize("Ofast")
#pragma GCC optimize("inline")
#pragma GCC optimize("-fgcse")
#pragma GCC optimize("-fgcse-lm")
#pragma GCC optimize("-fipa-sra")
#pragma GCC optimize("-ftree-pre")
#pragma GCC optimize("-ftree-vrp")
#pragma GCC optimize("-fpeephole2")
#pragma GCC optimize("-ffast-math")
#pragma GCC optimize("-fsched-spec")
#pragma GCC optimize("unroll-loops")
#pragma GCC optimize("-falign-jumps")
#pragma GCC optimize("-falign-loops")
#pragma GCC optimize("-falign-labels")
#pragma GCC optimize("-fdevirtualize")
#pragma GCC optimize("-fcaller-saves")
#pragma GCC optimize("-fcrossjumping")
#pragma GCC optimize("-fthread-jumps")
#pragma GCC optimize("-funroll-loops")
#pragma GCC optimize("-freorder-blocks")
#pragma GCC optimize("-fschedule-insns")
#pragma GCC optimize("inline-functions")
#pragma GCC optimize("-ftree-tail-merge")
#pragma GCC optimize("-fschedule-insns2")
#pragma GCC optimize("-fstrict-aliasing")
#pragma GCC optimize("-falign-functions")
#pragma GCC optimize("-fcse-follow-jumps")
#pragma GCC optimize("-fsched-interblock")
#pragma GCC optimize("-fpartial-inlining")
#pragma GCC optimize("no-stack-protector")
#pragma GCC optimize("-freorder-functions")
#pragma GCC optimize("-findirect-inlining")
#pragma GCC optimize("-fhoist-adjacent-loads")
#pragma GCC optimize("-frerun-cse-after-loop")
#pragma GCC optimize("inline-small-functions")
#pragma GCC optimize("-finline-small-functions")
#pragma GCC optimize("-ftree-switch-conversion")
#pragma GCC optimize("-foptimize-sibling-calls")
#pragma GCC optimize("-fexpensive-optimizations")
#pragma GCC optimize("inline-functions-called-once")
#pragma GCC optimize("-fdelete-null-pointer-checks")
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+5;
#define re register
int n,m,k,l,r,top,t,len;
int root,ncnt,fa[N*5],size[N*5],cnt[N*5],val[N*5],ch[N*5][2];
int a[N],ru[N],chu[N],rev[N],head[N],Ans[N],gs[N],used[N],f[N][20];
struct node{
int l,r,id,lca,k;
}q[N];
struct node2{
int too,next;
}edge[N];
vector<int>v[N];
char buf[1<<21],*p1=buf,*p2=buf;
inline int gc(){return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++;}
inline int read()
{
int ret=0,f=0;char c=gc();
while(!isdigit(c)){if(c=='-')f=1;c=gc();}
while(isdigit(c)){ret=ret*10+c-48;c=gc();}
if(f)return -ret;return ret;
}
void write(int x){
if(x>=10) write(x/10);
putchar(x%10+48);
}
inline void writeln(int x){
write(x);
putchar('\n');
}
inline bool chk(int x)
{
return ch[fa[x]][1]==x;
}
inline void pushup(int x)
{
size[x]=size[ch[x][0]]+size[ch[x][1]]+cnt[x];
}
inline void Zhuan(int x)
{
int y=fa[x],z=fa[y],k=chk(x),w=ch[x][k^1];
ch[y][k]=w;
fa[w]=y;
ch[z][chk(y)]=x;
fa[x]=z;
ch[x][k^1]=y;
fa[y]=x;
pushup(y);pushup(x);
}
inline void splay(int x,int gen=0)
{
while(fa[x]!=gen)
{
int y=fa[x],z=fa[y];
if(z!=gen)
{
if(chk(x)==chk(y))Zhuan(y);
else Zhuan(x);
}
Zhuan(x);
}
if(!gen)root=x;
}
inline void insert(int x)
{
int u=root,p=0;
while(u&&val[u]!=x)
{
p=u;
u=ch[u][x>val[u]];
}
if(u)cnt[u]++;
else{
u=++ncnt;
fa[u]=p;
ch[p][x>val[p]]=u;
ch[u][0]=ch[u][1]=0;
size[u]=cnt[u]=1;
val[u]=x;
}
splay(u);
}
inline int kth(int x)
{
int u=root;
while(true)
{
if(ch[u][0]&&x<=size[ch[u][0]])u=ch[u][0];
else if(x>size[ch[u][0]]+cnt[u])
{
x-=size[ch[u][0]]+cnt[u];
u=ch[u][1];
}
else return u;
}
}
inline void find(int x)
{
int u=root;
while(x!=val[u]&&ch[u][x>val[u]])u=ch[u][x>val[u]];
splay(u);
}
inline int pre(int x)
{
find(x);
if(val[root]<x)return root;
int u=ch[root][0];
while(ch[u][1])u=ch[u][1];
return u;
}
inline int nxt(int x)
{
find(x);
if(val[root]>x)return root;
int u=ch[root][1];
while(ch[u][0])u=ch[u][0];
return u;
}
inline void Delete(int x)
{
int last=pre(x),next=nxt(x);
splay(last);
splay(next,last);
int del=ch[next][0];
if(cnt[del]>1)
{
cnt[del]--;
splay(del);
}
else ch[next][0]=0;
}
inline void add(int a,int b)
{
edge[++top].too=b;edge[top].next=head[a];head[a]=top;
}
void dfs(int u,int fa)
{
ru[u]=++t;rev[t]=u;
f[u][0]=fa;
for(re int i=head[u];i;i=edge[i].next)
{
int v=edge[i].too;
if(v==fa)continue;
dfs(v,u);
}
chu[u]=++t;rev[t]=u;
}
inline bool pd(int a,int b)
{
if((ru[b]<=ru[a])&&(chu[b]>=chu[a]))return true;
return false;
}
inline int LCA(int x,int y)
{
if(pd(x,y))return y;
if(pd(y,x))return x;
int k=x;
for(re int j=17;j>=0;j--)
if((f[k][j]>0)&&(pd(y,f[k][j])==false))k=f[k][j];
return f[k][0];
}
inline bool cmp(node a,node b)
{
return ((a.l/len)^(b.l/len))?(a.l<b.l):((a.l/len)&1)?(a.r<b.r):(a.r>b.r);
}
inline void add(int x)
{
for(re int i=0;i<v[x].size();i++)
{
gs[v[x][i]]++;
if(gs[v[x][i]]==2)insert(a[v[x][i]]);
}
}
inline void del(int x)
{
for(re int i=0;i<v[x].size();i++)
{
gs[v[x][i]]--;
if(gs[v[x][i]]==1)Delete(a[v[x][i]]);
}
}
inline void Add(int x)
{
if(used[x])del(x);
else add(x);
used[x]^=1;
}
int main()
{
n=read();m=read();k=read();
for(re int i=1;i<n;i++)
{
int x=read(),y=read();
add(x,y);add(y,x);
}
for(re int i=1;i<=m;i++)
{
int x=read(),y=read();
a[i]=read();
v[x].push_back(i);
v[y].push_back(i);
}
dfs(1,0);
for(re int i=1;i<=17;i++)
for(re int j=1;j<=n;j++)
f[j][i]=f[f[j][i-1]][i-1];
len=sqrt(n);
for(re int i=1;i<=k;i++)
{
q[i].id=i;
int x=read(),y=read();
q[i].k=read();
if(ru[x]>ru[y])swap(x,y);
int lca=LCA(x,y);
if(lca==x)q[i].l=ru[x],q[i].r=ru[y],q[i].lca=0;
else q[i].l=chu[x],q[i].r=ru[y],q[i].lca=lca;
}
sort(q+1,q+k+1,cmp);
l=1;insert(1e9+1);insert(-1e9-1);
for(re int i=1;i<=k;i++)
{
while(l>q[i].l){l--;Add(rev[l]);}
while(r<q[i].r){r++;Add(rev[r]);}
while(l<q[i].l){Add(rev[l]);l++;}
while(r>q[i].r){Add(rev[r]);r--;}
if(q[i].lca)Add(q[i].lca);
Ans[q[i].id]=val[kth(q[i].k+1)];
if(q[i].lca)Add(q[i].lca);
}
for(int i=1;i<=k;i++)writeln(Ans[i]);
return 0;
} (分块)
// luogu-judger-enable-o2
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize("Ofast")
#pragma GCC optimize("inline")
#pragma GCC optimize("-fgcse")
#pragma GCC optimize("-fgcse-lm")
#pragma GCC optimize("-fipa-sra")
#pragma GCC optimize("-ftree-pre")
#pragma GCC optimize("-ftree-vrp")
#pragma GCC optimize("-fpeephole2")
#pragma GCC optimize("-ffast-math")
#pragma GCC optimize("-fsched-spec")
#pragma GCC optimize("unroll-loops")
#pragma GCC optimize("-falign-jumps")
#pragma GCC optimize("-falign-loops")
#pragma GCC optimize("-falign-labels")
#pragma GCC optimize("-fdevirtualize")
#pragma GCC optimize("-fcaller-saves")
#pragma GCC optimize("-fcrossjumping")
#pragma GCC optimize("-fthread-jumps")
#pragma GCC optimize("-funroll-loops")
#pragma GCC optimize("-freorder-blocks")
#pragma GCC optimize("-fschedule-insns")
#pragma GCC optimize("inline-functions")
#pragma GCC optimize("-ftree-tail-merge")
#pragma GCC optimize("-fschedule-insns2")
#pragma GCC optimize("-fstrict-aliasing")
#pragma GCC optimize("-falign-functions")
#pragma GCC optimize("-fcse-follow-jumps")
#pragma GCC optimize("-fsched-interblock")
#pragma GCC optimize("-fpartial-inlining")
#pragma GCC optimize("no-stack-protector")
#pragma GCC optimize("-freorder-functions")
#pragma GCC optimize("-findirect-inlining")
#pragma GCC optimize("-fhoist-adjacent-loads")
#pragma GCC optimize("-frerun-cse-after-loop")
#pragma GCC optimize("inline-small-functions")
#pragma GCC optimize("-finline-small-functions")
#pragma GCC optimize("-ftree-switch-conversion")
#pragma GCC optimize("-foptimize-sibling-calls")
#pragma GCC optimize("-fexpensive-optimizations")
#pragma GCC optimize("inline-functions-called-once")
#pragma GCC optimize("-fdelete-null-pointer-checks")
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+5;
#define re register
int n,m,k,l,r,top,t,len;
int root,ncnt,size,num,xu[N],sum[N],bel[N],L[N],R[N],b[N];
int a[N],ru[N],chu[N],rev[N],head[N],Ans[N],gs[N],used[N],f[N][20];
struct node{
int l,r,id,lca,k;
}q[N];
struct node2{
int too,next;
}edge[N];
vector<int>v[N];
//char buf[1<<21],*p1=buf,*p2=buf;
//inline int gc(){return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++;}
#define gc getchar
inline int read()
{
int ret=0,f=0;char c=gc();
while(!isdigit(c)){if(c=='-')f=1;c=gc();}
while(isdigit(c)){ret=ret*10+c-48;c=gc();}
if(f)return -ret;return ret;
}
void write(int x){
if(x>=10) write(x/10);
putchar(x%10+48);
}
inline void writeln(int x){
write(x);
putchar('\n');
}
inline void insert(int x)
{
xu[x]++;sum[bel[x]]++;
}
inline void Delete(int x)
{
xu[x]--;sum[bel[x]]--;
}
inline void add(int a,int b)
{
edge[++top].too=b;edge[top].next=head[a];head[a]=top;
}
void dfs(int u,int fa)
{
ru[u]=++t;rev[t]=u;
f[u][0]=fa;
for(re int i=head[u];i;i=edge[i].next)
{
int v=edge[i].too;
if(v==fa)continue;
dfs(v,u);
}
chu[u]=++t;rev[t]=u;
}
inline bool pd(int a,int b)
{
if((ru[b]<=ru[a])&&(chu[b]>=chu[a]))return true;
return false;
}
inline int LCA(int x,int y)
{
if(pd(x,y))return y;
if(pd(y,x))return x;
int k=x;
for(re int j=17;j>=0;j--)
if((f[k][j]>0)&&(pd(y,f[k][j])==false))k=f[k][j];
return f[k][0];
}
inline bool cmp(node a,node b)
{
return ((a.l/len)^(b.l/len))?(a.l<b.l):((a.l/len)&1)?(a.r<b.r):(a.r>b.r);
}
inline void add(int x)
{
for(re int i=0;i<v[x].size();i++)
{
gs[v[x][i]]++;
if(gs[v[x][i]]==2)insert(a[v[x][i]]);
}
}
inline void del(int x)
{
for(re int i=0;i<v[x].size();i++)
{
gs[v[x][i]]--;
if(gs[v[x][i]]==1)Delete(a[v[x][i]]);
}
}
inline void Add(int x)
{
if(used[x])del(x);
else add(x);
used[x]^=1;
}
inline int query(int x)
{
int i,S=0;
for(i=1;i<=num;i++)
{
S+=sum[i];
if(S>=x)break;
}
for(int j=R[i];j>=L[i];j--)
{
if(S>x-xu[j]&&S<=x)return b[j];
S-=xu[j];
}
}
int main()
{
n=read();m=read();k=read();
for(re int i=1;i<n;i++)
{
int x=read(),y=read();
add(x,y);add(y,x);
}
for(re int i=1;i<=m;i++)
{
int x=read(),y=read();
a[i]=b[i]=read();
v[x].push_back(i);
v[y].push_back(i);
}
sort(b+1,b+m+1);
size=unique(b+1,b+m+1)-b-1;
for(int i=1;i<=m;i++)a[i]=lower_bound(b+1,b+size+1,a[i])-b;
int sz=sqrt(m);
num=m/sz;
if(m%sz)num++;
for(int i=1;i<=m;i++)L[i]=m+1;
for(int i=1;i<=m;i++)
{
bel[i]=(i-1)/sz+1;
L[bel[i]]=min(L[bel[i]],i);
R[bel[i]]=max(R[bel[i]],i);
}
dfs(1,0);
for(re int i=1;i<=17;i++)
for(re int j=1;j<=n;j++)
f[j][i]=f[f[j][i-1]][i-1];
len=sqrt(n);
for(re int i=1;i<=k;i++)
{
q[i].id=i;
int x=read(),y=read();
q[i].k=read();
if(ru[x]>ru[y])swap(x,y);
int lca=LCA(x,y);
if(lca==x)q[i].l=ru[x],q[i].r=ru[y],q[i].lca=0;
else q[i].l=chu[x],q[i].r=ru[y],q[i].lca=lca;
}
sort(q+1,q+k+1,cmp);
l=1;
for(re int i=1;i<=k;i++)
{
while(l>q[i].l){l--;Add(rev[l]);}
while(r<q[i].r){r++;Add(rev[r]);}
while(l<q[i].l){Add(rev[l]);l++;}
while(r>q[i].r){Add(rev[r]);r--;}
if(q[i].lca)Add(q[i].lca);
Ans[q[i].id]=query(q[i].k);
if(q[i].lca)Add(q[i].lca);
}
for(int i=1;i<=k;i++)writeln(Ans[i]);
return 0;
} 
京公网安备 11010502036488号