传送门

不要…不要误会,我不是针对莫队,我是说在座的莫队都假了。

(虽然我也写的假莫队)

给你一棵树和若干条带权模式链,多次询问,给出一条链,求所有为其子链的模式链中,权值第$k$小是多少。

用树上莫队+分块解决。

关键在于怎么判断某条模式链是否为当前区间代表的链的子链。

首先能想到每个点开一个vector,把每个模式链插进两端点的vector中。移动指针时,扫一遍vector,如果一条链的另一个端点也位于当前链,就把它加进块里/从块里删除。

但这个做法复杂度对吗?

vector存信息时,必须保证每个vector被遍历的次数是均等的,才能把复杂度均摊掉。

显然莫队不能保证每个位置被扫过的次数是均等的。通俗来讲,莫队的指针移动次数是$O(n\sqrt{m})$的,但每个位置被扫过的次数不是$O(\sqrt{m})$的

这样卡掉这个做法就很容易了,将模式链全部插入第一个块里,询问左端点也全放到第一个块里,构造右端点,使排序后的询问左端点会呈这种方式移动:

复杂度就是$O(nm)$的。只不过数据水没卡。

解决方案:把每个位置按vector的元素拆成若干个新点,重新制定询问区间。在新序列和新询问区间上跑莫队。

然而这样写很麻烦,细节很繁琐,所以我还是写的假莫队

代码:

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <vector>

#define maxn 80005
#define inf 0x3f3f3f3f

using namespace std;

inline int read(){
    int x=0,y=0;
    char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')y=1;ch=getchar();}
    while(ch>='0'&&ch<='9')x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
    return y?-x:x;
}
int son[maxn],siz[maxn],seg[maxn],deep[maxn],fa[maxn],top[maxn],dis[maxn],ans[maxn],len;
int fir[maxn],en[maxn],be[maxn],pos[maxn],h[maxn],bel[maxn],bc[maxn],c[maxn],num,cnt,all;
vector<pair<int,int> >p[maxn];
vector<pair<int,int> >::iterator iter;
bool vis[maxn];
struct edge{
    int pre,to;
}e[maxn];
struct Query{
    int l,r,num,lc,k;
    bool operator < (const Query &x)const{
        if(be[l]!=be[x.l])return be[l]<be[x.l];
        if(be[l]&1)return r<x.r;
        return r>x.r;
    }
}q[maxn>>1];
inline void adde(int from,int to){
    e[++num]=(edge){h[from],to};
    h[from]=num;
}
void dfs1(int node=1){
    pos[fir[node]=++cnt]=node;
    siz[node]=1;
    for(register int i=h[node],x;i;i=e[i].pre){
        x=e[i].to;
        if(siz[x])continue;
        deep[x]=deep[node]+1,fa[x]=node;
        dfs1(x),siz[node]+=siz[x];
        if(siz[x]>siz[son[node]])son[node]=x;
    }
    pos[en[node]=++cnt]=node;
}
void dfs2(int node=1){
    seg[node]=++all;
    if(!son[node])return;
    int x;
    top[son[node]]=top[node],dfs2(son[node]);
    for(register int i=h[node],x;i;i=e[i].pre){
        x=e[i].to;
        if(!seg[x])top[x]=x,dfs2(x);
    }
}
int lca(int x,int y){
    while(top[x]!=top[y])deep[top[x]]<deep[top[y]]?y=fa[top[y]]:x=fa[top[x]];
    return deep[x]<deep[y]?x:y;
}
void process(int x,int y,int k,int i){
    int l=lca(x,y);
    if(l!=x&&l!=y){
        if(en[x]>fir[y])swap(x,y);
        q[i]=(Query){en[x],fir[y],i,l,k};
    }
    else {
        if(l==y)swap(x,y);
        q[i]=(Query){fir[x],fir[y],i,0,k};
    }
}
inline void add(int x){++c[x],++bc[bel[x]];}
inline void del(int x){--c[x],--bc[bel[x]];}
inline void modify(int x){
    vis[x]^=1;
    if(!vis[x]){
        for(iter=p[x].begin();iter!=p[x].end();++iter)
            if(vis[iter->first])del(iter->second);
    }
    else {
        for(iter=p[x].begin();iter!=p[x].end();++iter)
            if(vis[iter->first])add(iter->second);
    }
}
int main(){
    int n=read(),m=read(),t=read(),sq,L,ssq,x,y,z;
    for(register int i=1;i<n;++i)x=read(),y=read(),adde(x,y),adde(y,x);
    dfs1(),dfs2();
    sq=cnt/sqrt(t),L=cnt/sq+bool(cnt%sq);
    for(register int i=1;i<=L;++i)
        for(register int j=sq*(i-1)+1,r=min(cnt,j+sq-1);j<=r;++j)
            be[j]=i;
    while(m--){
        x=read(),y=read(),dis[++len]=z=read();
        p[x].push_back(make_pair(y,z)),p[y].push_back(make_pair(x,z));
    }
    sort(dis+1,dis+1+len);
    len=unique(dis+1,dis+1+len)-dis-1;
    ssq=sqrt(len),L=len/ssq+bool(len%ssq);
    for(register int i=1;i<=L;++i)
        for(register int j=ssq*(i-1)+1,r=min(len,j+ssq-1);j<=r;++j)
            bel[j]=i;
    for(register int i=1;i<=n;++i)
        for(iter=p[i].begin();iter!=p[i].end();++iter)
            iter->second=lower_bound(dis+1,dis+1+len,iter->second)-dis;
    for(register int i=1;i<=t;++i){
        x=read(),y=read(),z=read();
        process(x,y,z,i);
    }
    sort(q+1,q+1+t);
    int l=1,r=1,j;
    modify(pos[1]);
    for(register int i=1;i<=t;++i){
        while(l<q[i].l)modify(pos[l++]);
        while(l>q[i].l)modify(pos[--l]);
        while(r<q[i].r)modify(pos[++r]);
        while(r>q[i].r)modify(pos[r--]);
        if(q[i].lc)modify(q[i].lc);
        for(j=1;j<=L&&q[i].k>bc[j];++j)q[i].k-=bc[j];
        for(j=(j-1)*ssq+1,x=min(n,j+ssq-1);j<=x&&q[i].k>c[j];++j)q[i].k-=c[j];
        if(q[i].lc)modify(q[i].lc);
        ans[q[i].num]=dis[j];
    }
    for(register int i=1;i<=t;++i)printf("%d\n",ans[i]);
}