100分的做法:
當p>sqrt(n)時, 這時候%p=c的點不超過sqrt(n)個, 直接倍增求路徑最值就好了
當p<=sqrt(n)時,將詢問離線, 按照p和c從小到大排序,同時處理出所有p相同且c相同的區間詢問
對於同一個p[i]和c[i],將所有%p[i]=c[i]的點, 兩兩(c[j]和c[j]+p)求路徑最大值, 並將這個相鄰最大值更新到線段樹上, 對於一個區間的詢問, 直接從線段樹上查[l,r]的區間最值
#pragma GCC optimize(2)
#include <cstdio>
#include <algorithm>
#include <vector>
#include <iterator>
#include <cmath>
#include <cstring>
#include <utility>
const int maxn = 5e4 + 5;
struct node
{
int u,v,w;
bool operator<(const node &x)const
{
return w<x.w;
}
}edge[200005];
std::vector<node> v;
std::vector<std::pair<int,int> > G[maxn];
int a[maxn],res[maxn],dep[maxn],fa[maxn],Fa[maxn][17],ma[maxn][17],n,m,q;
int find(int x){return x==fa[x]?x:fa[x]=find(fa[x]);}
void dfs(int u,int fa)
{
dep[u]=dep[fa]+1;
Fa[u][0]=fa;
for(int i=1;(1<<i)<=dep[u];i++)
Fa[u][i]=Fa[Fa[u][i-1]][i-1],
ma[u][i]=std::max(ma[u][i-1],ma[Fa[u][i-1]][i-1]);
for(std::vector<std::pair<int,int> >::iterator i=G[u].begin();i!=G[u].end();++i)
{
if(i->first==fa) continue;
ma[i->first][0]=i->second;
dfs(i->first,u);
}
}
int getlca_max(int x,int y)
{
int ans=-0x3f3f3f3f;
if(dep[x]<dep[y]) std::swap(x,y);
for(int i=16;i>=0;i--) if((1<<i)<=dep[x]-dep[y])
ans=std::max(ans,ma[x][i]),x=Fa[x][i];
if(x==y) return ans;
for(int i=16;i>=0;i--)
if(Fa[x][i]!=Fa[y][i])
ans=std::max(ans,std::max(ma[y][i],ma[x][i])),
x=Fa[x][i],y=Fa[y][i];
return std::max(ans,std::max(ma[x][0],ma[y][0]));
}
struct SegTree
{
int maxx[maxn<<2];
void build(int o,int l,int r)
{
maxx[o]=0;
if(l==r){maxx[o]=a[l];return ;}
int m=(l+r)>>1;
build(o<<1,l,m);build(o<<1|1,m+1,r);
maxx[o]=std::max(maxx[o<<1],maxx[o<<1|1]);
}
int query(int o,int l,int r,int ql,int qr)
{
if(ql<=l&&r<=qr)return maxx[o];
int m=(l+r)>>1;
int ans=-0x3f3f3f3f;
if(ql<=m) ans=std::max(ans,query(o<<1,l,m,ql,qr));
if(qr>m) ans=std::max(ans,query(o<<1|1,m+1,r,ql,qr));
return ans;
}
}st;
struct query
{
int l,r,mod,c,id;
bool operator<(const query &x)const
{
if(mod==x.mod)return c<x.c;
else return mod<x.mod;
}
}Q[maxn];
int main()
{
#ifdef LOCAL
freopen("input.in","r",stdin);
#endif
scanf("%d%d%d",&n,&m,&q);
for(int i=1;i<=n;i++) fa[i]=i;
for(int i=1;i<=m;i++)
{
scanf("%d%d%d",&edge[i].u,&edge[i].v,&edge[i].w);
}
std::sort(edge+1,edge+m+1);
int cnt=0;
for(int i=1;i<=m;i++)
{
int x=find(edge[i].u),y=find(edge[i].v);
if(x!=y)
{
fa[x]=y;cnt++;
G[edge[i].u].push_back(std::make_pair(edge[i].v,edge[i].w));
G[edge[i].v].push_back(std::make_pair(edge[i].u,edge[i].w));
}
if(cnt==n-1)break;
}
dfs(1,0);
for(int i=1;i<=q;i++)
{
int l,r,mod,c;scanf("%d%d%d%d",&Q[i].l,&Q[i].r,&Q[i].mod,&Q[i].c);
Q[i].id=i;
}
std::sort(Q+1,Q+q+1);
for(int i=1;i<=q;i++)
{
int l=Q[i].l,r=Q[i].r,mod=Q[i].mod,c=Q[i].c;
if(mod>sqrt(n))
{
int L=l-l%mod+c; if(L<l)L+=mod;
int ans=-0x3f3f3f3f;
for(int j=L;j<=r-mod;j+=mod)
ans=std::max(ans,getlca_max(j,j+mod));
res[Q[i].id]=ans;
}
else
{
if(Q[i].mod!=Q[i-1].mod||Q[i].c!=Q[i-1].c)
{
memset(a,0,sizeof a);
for(int j=c?c:mod;j+mod<=n;j+=mod)
a[j]=getlca_max(j,j+mod);
st.build(1,1,n);
}
res[Q[i].id]=st.query(1,1,n,l,r-mod);
}
}
for(int i=1;i<=q;i++)printf("%d\n",res[i]);
return 0;
}