4537: [Hnoi2016] least common multiple time limit: $ Sec Memory Limit: MB
Submit: 563 Solved: 236
[Submit] [Status] [Discuss] Description
Given a graph of n vertex m edges (vertex numbered,..., N) with weights on each edge. The ownership value can be decomposed into 2^a*3^b
The form. Now there are Q queries, each time you ask for a given four parameters U, V, a and B, please find out if there is a path between the vertex u to V, making
The least common multiple of the weighted value on the edge of the path is 2^a*3^b. Note: The path may not be a simple path. Here are some definitions that might be useful
: least common multiple: K number A1,A2,..., ak Least common multiple is the smallest positive integer that can be divisible by each AI. Path: path P:P1,P2,..., PK is the top
Point sequence, satisfies for any 1<=i<k, the node pi and the pi+1 have the edge to connect. Simple path: If the path p:p1,p2,..., PK, for any 1
<=s≠t<=k all have ps≠pt, then the path is called a simple path.
Input
The first line of the input file contains two integers n and m, representing the number of vertices and sides of the graph, respectively. Next m line, each line contains four integers u, V, a,
b represents a vertex between U and V, with a weight of 2^a*3^b edge. The next line contains an integer q, which represents the number of queries. Next Q line, each row contains four
integers u, V, a, and b represent a single query. Please refer to the question description for more information. 1<=n,q<=50000, 1<=m<=100000, 0<=a,b<=10^9
Output
For each query, if there is a path that satisfies the condition, the output line is yes, otherwise the output is one line No (note: The first letter is capitalized, the remaining
Letter lowercase).
Sample Input4 5
1 2 1 3
1 3 1 2
1 4 2 1
2 4 3 2
3 4 2 2
5
1 4 3 3
4 2 2 3
1 3 2 2
2 3 2 2
1 3 4 4Sample OutputYes
Yes
Yes
No
No
chunking Good question
The problem turns out to be two weights A and b per side, each asking if there is a path between two points that satisfies the maximum value of a on the path and the maximum value of B is equal to one number.
Sort the edges by a, then block them.
The range of a is processed every time a query is within the current block. Assuming that the block I is processed, the query and the former i-1 block are sorted by B, and these parts O (n) can be processed. Block I in the side of violence treatment, and then undo the modification. Then use a and check set to maintain the maximum value of the collection.
#include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <cmath > #include <algorithm> #define F (I,j,n) for (int. i=j;i<=n;i++) #define D (i,j,n) for (int i=j;i>=n;i--) # Define ll long Long#define N 200005#define inf 1000000000using namespace Std;int N,m,q,block,cnt,tot,f[n],sz[n],mxa[n], Mxb[n];bool ans[n];struct data{int X,y,a,b,id;} A[n],b[n],c[n];struct opt{int X,y,f,mxa,mxb,sz;} Op[n];inline int read () {int X=0,f=1;char ch=getchar (); while (ch< ' 0 ' | | Ch> ' 9 ') {if (ch== '-') F=-1;ch=getchar ();} while (ch>= ' 0 ' &&ch<= ' 9 ') {x=x*10+ch-' 0 '; Ch=getchar ();} return x*f;} inline bool Cmpa (const data &a,const data &b) {return A.A==B.A?A.B<B.B:A.A<B.A;} inline bool CMPB (const data &a,const data &b) {return a.b==b.b?a.a<b.a:a.b<b.b;} int find (int x,int flg) {if (f[x]==x) return x;if (FLG) op[++tot]= (opt) {X,0,f[x],0,0,0};return f[x]=find (F[X],FLG);} void merge (int x,int y,int a,int b,int flg) {x=find (X,FLG); Y=find (Y,FLG), if (Sz[x]<sz[y]) swap (x, y), if (FLG) op[++tot]= (opt) {x,y,f[y],mxa[x],mxb[x],sz[x]};if (x==y) {Mxa[x]=max (mxa[x], a); Mxb[x]=max (mxb[x],b); return;} F[y]=x;sz[x]+=sz[y];mxa[x]=max (Mxa[x],max (Mxa[y],a)); Mxb[x]=max (Mxb[x],max (Mxb[y],b));} int main () {n=read (); M=read (); block=sqrt (m); F (i,1,m) {a[i].x=read (); A[i].y=read (); A[i].a=read (); A[i].b=read (); a[i].id=i;} Sort (A+1,a+m+1,cmpa); Q=read (); F (i,1,q) {b[i].x=read (); B[i].y=read (); B[i].a=read (); B[i].b=read (); b[i].id=i;} Sort (B+1,B+Q+1,CMPB); for (int i=1;i<=m;i+=block) {cnt=0; F (J,1,Q) if (b[j].a>=a[i].a&& (i+block>m| | B[J].A<A[I+BLOCK].A)) C[++cnt]=b[j];sort (A+1,A+I,CMPB); F (j,1,n) f[j]=j,sz[j]=1,mxa[j]=mxb[j]=-inf;for (int j=1,k=1;j<=cnt;j++) {for (; k<i&&a[k].b<=c[j].b ; k++) merge (a[k].x,a[k].y,a[k].a,a[k].b,0); tot=0; F (L,i,min (i+block-1,m)) if (a[l].a<=c[j].a&&a[l].b<=c[j].b) merge (a[l].x,a[l].y,a[l].a,a[l].b,1); int X=find (c[j].x,1), Y=find (c[j].y,1), ans[c[j].id]= (x==y) && (mxa[x]==c[j].a) && (mxb[x]==C[J].B);D(l,tot,1) {if (!OP[L].Y) f[op[l].x]=op[l].f;else{f[op[l].y]=op[l].f;mxa[op[l].x]=op[l].mxa;mxb[op[l]. X]=op[l].mxb;sz[op[l].x]=op[l].sz;}}}} F (I,1,q) puts (Ans[i]? " Yes ":" No "); return 0;}
bzoj4537 "HNOI2016" least common multiple