Description
Input
Output
Sample Input1
1
4 3
1 2 50 1
2 3 100 2
3 4 50 1
5 0 2
3 0
2 1
4 1
3 1
3 2
4 3
1 2 50 1
2 3 100 2
3 4 50 1
5 0 2
3 0
2 1
4 1
3 1
3 2
Sample Output1
0
50
200
50
150
50
200
50
150
Sample Input2
1
5 5
1 2 1 2
2 3 1 2
4 3 1 2
5 3 1 2
1 5 2 1
4 1 3
5 1
5 2
2 0
4 0
5 5
1 2 1 2
2 3 1 2
4 3 1 2
5 3 1 2
1 5 2 1
4 1 3
5 1
5 2
2 0
4 0
Sample Output2
0
2
3
1
HINT
Solution
会了可持久化并查集这题可能会被卡的正解就很好写了……
把边按高度大小从大到小加入,用可持久化并查集记下每一个时刻并查集的联通情况,
同时用持久化的$Min[i]$数组记录$i$点所在的连通块内到点$1$的最近距离。查询的时候二分到对应时刻的并查集直接查询就行了。
Code
1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 #include<queue> 5 #include<algorithm> 6 #define N (200009) 7 using namespace std; 8 9 struct Edge{int to,next,len;}edge[N<<2]; 10 struct Sgt{int ls,rs,v;}; 11 struct Line 12 { 13 int u,v,w,h; 14 bool operator < (const Line &a) const {return h>a.h;} 15 }l[N<<1]; 16 struct Node 17 { 18 int num,dis; 19 bool operator < (const Node &a) const {return dis>a.dis;} 20 }; 21 int T,n,m,u,v,w,h,q,k,s,v0,p0,ans; 22 int dis[N],head[N],num_edge; 23 bool vis[N]; 24 priority_queue<Node>Q; 25 26 struct Chairman_Tree 27 { 28 Sgt a[N*40]; 29 int sgt_num,b[N],Root[N<<1]; 30 31 int Build(int l,int r) 32 { 33 int now=++sgt_num; 34 if (l==r) {a[now].v=b[l]; return now;} 35 int mid=(l+r)>>1; 36 a[now].ls=Build(l,mid); 37 a[now].rs=Build(mid+1,r); 38 return now; 39 } 40 int Update(int pre,int l,int r,int x,int v) 41 { 42 int now=++sgt_num; 43 a[now].ls=a[pre].ls; 44 a[now].rs=a[pre].rs; 45 if (l==r) {a[now].v=v; return now;} 46 int mid=(l+r)>>1; 47 if (x<=mid) a[now].ls=Update(a[now].ls,l,mid,x,v); 48 else a[now].rs=Update(a[now].rs,mid+1,r,x,v); 49 return now; 50 } 51 int Query(int now,int l,int r,int x) 52 { 53 if (l==r) return a[now].v; 54 int mid=(l+r)>>1; 55 if (x<=mid) return Query(a[now].ls,l,mid,x); 56 else return Query(a[now].rs,mid+1,r,x); 57 } 58 }Fa,Dep,Min; 59 60 inline int read() 61 { 62 int x=0; char c=getchar(); 63 while (c<'0' || c>'9') c=getchar(); 64 while (c>='0' && c<='9') x=x*10+c-'0', c=getchar(); 65 return x; 66 } 67 68 void add(int u,int v,int w) 69 { 70 edge[++num_edge].to=v; 71 edge[num_edge].next=head[u]; 72 edge[num_edge].len=w; 73 head[u]=num_edge; 74 } 75 76 int Find(int x,int t) 77 { 78 int fa=Fa.Query(Fa.Root[t],1,n,x); 79 return x==fa?x:Find(fa,t); 80 } 81 82 void Dijkstra(int s) 83 { 84 memset(dis,0x7f,sizeof(dis)); 85 memset(vis,0,sizeof(vis)); 86 dis[s]=0; 87 Q.push((Node){s,0}); 88 while (!Q.empty()) 89 { 90 int x=Q.top().num; Q.pop(); 91 if (vis[x]) continue; vis[x]=1; 92 for (int i=head[x]; i; i=edge[i].next) 93 if (!vis[edge[i].to] && dis[x]+edge[i].len<dis[edge[i].to]) 94 { 95 dis[edge[i].to]=dis[x]+edge[i].len; 96 Q.push((Node){edge[i].to,dis[edge[i].to]}); 97 } 98 } 99 } 100 101 int main() 102 { 103 T=read(); 104 while (T--) 105 { 106 Fa.sgt_num=Dep.sgt_num=Min.sgt_num=0; 107 memset(head,0,sizeof(head)); num_edge=0; 108 ans=0; 109 n=read(); m=read(); 110 for (int i=1; i<=m; ++i) 111 { 112 u=read(); v=read(); w=read(); h=read(); 113 l[i]=(Line){u,v,w,h}; 114 add(u,v,w); add(v,u,w); 115 } 116 Dijkstra(1); 117 sort(l+1,l+m+1); 118 for (int i=1; i<=n; ++i) 119 Fa.b[i]=i, Dep.b[i]=1, Min.b[i]=dis[i]; 120 Fa.Root[0]=Fa.Build(1,n);; 121 Dep.Root[0]=Dep.Build(1,n); 122 Min.Root[0]=Min.Build(1,n); 123 for (int i=1; i<=m; ++i) 124 { 125 Fa.Root[i]=Fa.Root[i-1]; 126 Dep.Root[i]=Dep.Root[i-1]; 127 Min.Root[i]=Min.Root[i-1]; 128 int fx=Find(l[i].u,i),fy=Find(l[i].v,i); 129 if (fx==fy) continue; 130 int dfx=Dep.Query(Dep.Root[i],1,n,fx); 131 int dfy=Dep.Query(Dep.Root[i],1,n,fy); 132 if (dfx>dfy) swap(fx,fy); 133 Fa.Root[i]=Fa.Update(Fa.Root[i],1,n,fx,fy); 134 int d1=Min.Query(Min.Root[i],1,n,fx); 135 int d2=Min.Query(Min.Root[i],1,n,fy); 136 Min.Root[i]=Min.Update(Min.Root[i],1,n,fy,min(d1,d2)); 137 if (dfx==dfy) Dep.Root[i]=Dep.Update(Dep.Root[i],1,n,fy,dfy+1); 138 } 139 q=read(); k=read(); s=read(); 140 for (int i=1; i<=q; ++i) 141 { 142 v0=read(); p0=read(); 143 v0=(v0+k*ans-1)%n+1; 144 p0=(p0+k*ans)%(s+1); 145 int L=1,R=m,A=-1; 146 while (L<=R) 147 { 148 int mid=(L+R)>>1; 149 if (l[mid].h>p0) A=mid,L=mid+1; 150 else R=mid-1; 151 } 152 if (A==-1) 153 { 154 printf("%d ",dis[v0]); 155 ans=dis[v0]; continue; 156 } 157 int fx=Find(v0,A); 158 ans=Min.Query(Min.Root[A],1,n,fx); 159 printf("%d ",ans); 160 } 161 } 162 }