zoukankan      html  css  js  c++  java
  • HNOI2016最小公倍数


    (O(nq))把大于((a,b))的边加入,(u,v)在的连通块最小为((a,b))即可

    查两维又难删除,回滚莫队?

    又不要脸地去看标程了,貌似分了块,难不成是真的?

    等等等,又看错题了,是最小公倍数不是最大公约数

    仔细想想分块这个又是干啥的?可以把边按a排序,然后分块,a在一块内的一起处理询问,把后几块的重新b排序,依次加入,每个询问再单独加当前块的(和回滚莫队差不多,只不过多排一遍序)

    时间复杂度(O(mlogmsqrt{mlogm}))

    #include<bits/stdc++.h>
    using namespace std;
    inline int read(){
    	int x=0,f=1;char c=getchar();
    	while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
    	while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
    	return f==1?x:-x;
    }
    const int N=1e5+4;
    int n,m,Q,B,BB;
    int bb[N<<1],bl[N],br[N],ans[N]; 
    struct edge{int u,v,a,b;}e[N<<1],qe[N<<1];
    struct ques{int u,v,a,b,id,bk;}q[N];
    inline bool compa(const edge &x,const edge &y){
    	return x.a<y.a;
    }
    inline bool compb(const edge &x,const edge &y){
    	return x.b<y.b;
    }
    inline bool compq(const ques &x,const ques &y){
    	return x.bk==y.bk?x.b<y.b:x.bk<y.bk;
    }
    int top,fa[N],siz[N],mxa[N],mxb[N];
    int find(int x){
    	return fa[x]==x?x:find(fa[x]);
    }
    struct modi{int v,u,ma,mb,sz;}st[N];
    inline void add(edge x){
    	int fu=find(x.u),fv=find(x.v);
    	if(siz[fu]<siz[fv])fu^=fv^=fu^=fv;
    	st[++top]=(modi){fv,fu,mxa[fu],mxb[fu],siz[fu]};
    	mxa[fu]=max(mxa[fu],x.a);
    	mxb[fu]=max(mxb[fu],x.b);
    	if(fu==fv){
    		st[top].v=0;
    		return;
    	}
    	fa[fv]=fu;
    	siz[fu]+=siz[fv];
    	mxa[fu]=max(mxa[fu],mxa[fv]);
    	mxb[fu]=max(mxb[fu],mxb[fv]);
    }
    inline void delet(){
    	if(st[top].v)fa[st[top].v]=st[top].v;
    	int u=st[top].u;
    	mxa[u]=st[top].ma;
    	mxb[u]=st[top].mb;
    	siz[u]=st[top].sz;
    	top--;
    }
    int main(){
    	n=read();m=read();
    	for(int i=1,u,v,a,b;i<=m;i++){
    		u=read();v=read();a=read();b=read();
    		e[i]=(edge){u,v,a,b};
    	}
    	sort(e+1,e+m+1,compa);
    	B=sqrt(m*log(m));BB=1;
    	for(int i=1;i<=m;i+=B,BB++){
    		bl[BB]=i;br[BB]=min(m,i+B-1);
    		bb[BB]=e[br[BB]].a;
    	} 
    	bb[BB]=1000000007;bl[BB]=m+1;
    	Q=read();
    	for(int i=1,u,v,a,b,k;i<=Q;i++){
    		u=read();v=read();a=read();b=read();
    		k=upper_bound(bb+1,bb+BB+1,a)-bb;
    		q[i]=(ques){u,v,a,b,i,k};
    	}
    	sort(q+1,q+Q+1,compq);
    	for(int i=1,l,fu,fv;i<=Q;i++){
    		if(q[i].bk!=q[i-1].bk){
    			memcpy(qe,e,sizeof(e));
    			sort(qe+1,qe+bl[q[i].bk],compb);
    			l=1;top=0;
    			for(int j=1;j<=n;j++){
    				fa[j]=j;
    				mxa[j]=mxb[j]=-1;//
    				siz[j]=1;
    			}
    		}
    		while(l<bl[q[i].bk]&&qe[l].b<=q[i].b){
    			add(qe[l++]);
    		}
    		for(int j=bl[q[i].bk];j<=br[q[i].bk]&&qe[j].a<=q[i].a;j++){
    			if(qe[j].b<=q[i].b)add(qe[j]);
    		}
    		fu=find(q[i].u);fv=find(q[i].v);
    		if(fu==fv&&mxa[fu]==q[i].a&&mxb[fu]==q[i].b)ans[q[i].id]=1;
    		for(int j=bl[q[i].bk];j<=br[q[i].bk]&&qe[j].a<=q[i].a;j++){
    			if(qe[j].b<=q[i].b)delet();
    		}
    	}
    	for(int i=1;i<=Q;i++)
    		if(ans[i])puts("Yes");
    		else puts("No");
    	return (0-0);
    }
    
  • 相关阅读:
    flex 连接mysql
    正确配置调试world wind on vs2008
    FLex调用servlet连接数据库
    c# 连接mysql并webservice数据
    ADF连接SOM
    转载加收藏关于OPENGL配置VS2008
    flex不能显示本地发布的地图
    Symbian专区
    asp.net控件开发基础學習
    控制网页大小
  • 原文地址:https://www.cnblogs.com/aurora2004/p/12628674.html
Copyright © 2011-2022 走看看