首先跑一个最短路处理出每个点到源点距离(路径边权最大值,没有卡SPFA),然后按照这个距离排序,然后依次划分层次,我们可以观察到点的种类最多600个,那么就将困难值按愉悦值分段,先按点权排序,再跑一遍O(n)逐个标记就行
以上就是预处理阶段
然后解答询问就非常愉快了,直接枚举每一段的起点,然后将求解区间与该段的交集大小乘以每段的愉悦值相加就行了,复杂度是最短路SPFA:O(kn),排序O(nlogn),求解O(qmax(c)),总复杂度就是O(kn+nlogn+qmax(x)),能过掉这个题

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=1000005;
ll n,m,qq,x,opt;
struct node{
    ll w,v,lst;
}t[N];
struct node2{
    ll dis,id;
}d[N];
ll dis[N],head[N],tot,c[N],tott,h[N],M,ans,sum=-1,p[N];
queue<ll>q;
bool vis[N],vi[N];
void add(ll u,ll v,ll w){
    t[++tot].v=v;t[tot].w=w;t[tot].lst=head[u];head[u]=tot;
}
void spfa(){//最短路
    for(int i=1;i<=n;i++)
    {
        d[i].dis=1e9+1;
    }
    d[x].dis=0;
    q.push(x);
    while(!q.empty())
    {
        ll u=q.front();
        q.pop();
        vis[u]=false;
        for(int i=head[u];i;i=t[i].lst)
        {
            ll v=t[i].v,w=t[i].w;
            if(d[v].dis>max(d[u].dis,w))
            {
                d[v].dis=max(d[u].dis,w);
                if(vis[v]) continue;
                q.push(v);
                vis[v]=true;
            }
        }
    }
}
bool cmp(node2 x,node2 y){
    return x.dis<y.dis;
}
void init(){//分段
    sort(d+1,d+n+1,cmp);
    for(int i=1;i<=n;i++)
    {
        if(vi[c[d[i].id]]==false)
        {
            vi[c[d[i].id]]=true;
            tott++;
            if(d[i].dis>sum)
            {
                sum=d[i].dis;
                h[++h[0]]=d[i].dis;
            }
            p[h[0]]=tott;
        }
    }
}
void solve(ll l,ll r){//求解询问
    ll t=l;
    ans=0;
    for(int i=1;i<=h[0];i++)
    {
        if(h[i]>r)
        {
            ans+=(r-t+1)*(p[i-1]);
            break;
        }
        if(t<=h[i])
        {
            ans+=(h[i]-t)*(p[i-1]);
            t=h[i];
        }
    }
    if(r>=h[h[0]])
    {
        ans+=(r-t+1)*tott;
    }
    printf("%lld\n",ans);
}
int main()
{
    ll xx,y,w,l,r;
    scanf("%lld%lld%lld%lld%lld",&n,&m,&qq,&x,&opt);
    if(opt==1)
    {
        scanf("%lld",&M);
    }
    for(int i=1;i<=n;i++)
    {
        scanf("%lld",&c[i]);
        d[i].id=i;
    }
    for(int i=1;i<=m;i++)
    {
        scanf("%lld%lld%lld",&xx,&y,&w);
        add(xx,y,w);
        add(y,xx,w);
    }
    spfa();
    init();
    for(int i=1;i<=qq;i++)
    {
        scanf("%lld%lld",&l,&r);
        if(opt==1)
        {
            l=(l^ans)%M+1;
            r=(r^ans)%M+1;
        }
        if(l>r) swap(l,r);
        solve(l,r);
    }
}

顺便吐槽一下大样例太水
本人比赛时上面区间(r-t)忘了减一,水过了大样例,结果0分。。。。。。