不难发现,能否走到这个点仅与起点到这个点路径最小的最大值有关,因此显然可以先生成一棵生成树,然后统计答案。
然后对于每次询问,如果 比大于等于能走到的最小值,那么直接说明
都可以走,否则答案即为
然而数据太大,考虑离散化,此时破坏了 离散化成了一个区间,由于有在线数据,我们无法把
也离散化,因此考虑类似分块的方法,用两个树状数组,处理前缀和和前缀和的前缀和
注意第一个树状数组的意义是小于等于 这段区间能得到的愉悦值和,第二个树状数组的意义是
这个区间前缀和的愉悦值(
意为离散化之前的数,记得插入一个极大值)
然后就可以类似分块那样统计答案了,复杂度是
#include<iostream> #include<cmath> #include<cstdio> #include<cstring> #include<queue> #include<stack> #include<vector> #include<set> #include<map> #include<algorithm> #include<cstdlib> #include<ctime> #define int long long using namespace std; namespace mstd{ inline void qread(int &x) { x=0; int f=1; static char c=getchar(); while(!isdigit(c)) {if(c=='-') f=-f; c=getchar();} while(isdigit(c)) x=(x*10+c-'0'),c=getchar(); x*=f; } inline void mqread(long long &x) { x=0; long long f=1; static char c=getchar(); while(!isdigit(c)) {if(c=='-') f=-f; c=getchar();} while(isdigit(c)) x=(x*10+c-'0'),c=getchar(); x*=f; } } const int maxn=500500; int n,m,head[maxn],size; int q,st,opt,modp,f[maxn],lasans; int b[maxn],tot,C; int d[maxn],bl[maxn],cst[maxn]; struct ctree{ int c[maxn]; int lowbit(int x) { return x&(-x); } inline void add(int x,int target) { while(x<=C) c[x]+=target,x+=lowbit(x); return ; } inline int ask(int x) { int ans=0; while(x) ans+=c[x],x-=lowbit(x); return ans; } }st1,st2,st3; struct edge{ int next,to,dis; }e[maxn<<1]; struct medge{ int x,y,dis; bool operator <(const medge &ano) const { return dis<ano.dis; } }_e[maxn]; inline void addedge(int next,int to,int dis) { e[++size].to=to; e[size].dis=dis; e[size].next=head[next]; head[next]=size; } inline void getdis(int t,int fat) { int i,j,k; for(i=head[t];i;i=e[i].next) { j=e[i].to; if(j==fat) continue; k=e[i].dis; d[j]=max(k,d[t]); getdis(j,t); } } int getfather(int x) { if(x==f[x]) return x; return f[x]=getfather(f[x]); } inline void gettree() { int i,j; int p=0; for(i=1;i<=n;i++) f[i]=i; sort(_e+1,_e+m+1); for(i=1;i<=m;i++) { int x=_e[i].x; int y=_e[i].y; int edis=_e[i].dis; int xx=getfather(x); int yy=getfather(y); if(xx==yy) continue; p++; f[xx]=yy; addedge(x,y,edis); addedge(y,x,edis); if(p==n-1) break; } return ; } int cmst=0; int getans(int l,int r) { cmst++; int ll=l,ans; if(b[1]<=l) ans=upper_bound(b+1,b+tot+1,r)-b; else ans=0; ll=upper_bound(b+1,b+tot+1,l)-b; int rigsize=r-b[ans-1]+1; int lefsize=b[ll]-l; if(ll==ans) return (st2.ask(ll-1)*(r-l+1)); else if(ans-ll==1) return(st2.ask(ans-1)*(rigsize)+st2.ask(ll-1)*(lefsize)); else return(st2.ask(ans-1)*(rigsize)+st2.ask(ll-1)*(lefsize)+st3.ask(ans-2)-st3.ask(ll-1)); return 0; } inline void solve(int l,int r) { if(opt) {l=(l^lasans)%modp+1,r=(r^lasans)%modp+1;} l++,r++; if(l>r) swap(l,r); //printf("%d\n",lower_bound(b+1,b+tot+1,2)-b); printf("%lld\n",lasans=getans(l,r)); return ; } inline void _prework() { int i; for(i=1;i<=n;i++) st1.add(d[i],1); for(i=1;i<=600;i++) if(cst[i]!=0x3f3f3f3f) st2.add(cst[i],1); for(i=1;i<C;i++) st3.add(i,st2.ask(i)*(b[i+1]-b[i])); return ; } signed main() { // freopen("sample.in","r",stdin); // freopen("samplee.out","w",stdout); int i,j; mstd::qread(n); mstd::qread(m); mstd::qread(q); mstd::qread(st); mstd::qread(opt); if(opt) mstd::qread(modp); int t1,t2,t3; for(i=1;i<=n;i++) mstd::qread(bl[i]); for(i=1;i<=m;i++) { mstd::qread(t1); mstd::qread(t2); mstd::qread(t3); //cin>>t1>>t2>>t3; t3++; _e[i].x=t1; _e[i].y=t2; _e[i].dis=t3; } gettree(); d[st]=1; getdis(st,st); memset(cst,0x3f,sizeof(cst)); for(i=1;i<=n;i++) b[i]=d[i]; int sz=n; // for(i=1;i<=n;i++) // { // if(b[i]!=1) b[++sz]=b[i]-1; // b[++sz]=b[i]+1; // } sort(b+1,b+sz+1); b[++sz]=(int)1e9+20; sort(b+1,b+sz+1); tot=unique(b+1,b+sz+1)-b-1; C=tot; for(i=1;i<=n;i++) d[i]=lower_bound(b+1,b+tot+1,d[i])-b; for(i=1;i<=n;i++) cst[bl[i]]=min(cst[bl[i]],d[i]); _prework(); int l,r; for(i=1;i<=q;i++) { mstd::qread(l); mstd::qread(r); solve(l,r); } return 0; }