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

    如果信息只有一维,就可以直接排序,扫一遍的过程中用并查集来维护,也就是u和v需要连通且连通块内的最大边权等于询问的边权。现在有两维,我一开始还往分治的方向去想,但是询问所需要的在每一层中的信息不好合并,于是就考虑分块。
    首先把边按a排序,分块,把询问挂在第一个a大于询问a的那条边所在的块上,然后每一块内的边,每一块上的询问按b排序。
    从左往右扫每个块,并把这个块左边的所有边都加入并查集中,且这个块之前的边按b归并排序好,对于一个块中的询问,记一个指针表示这个块之前的那些块中最多可以加到哪条边(按b比较),然后暴力扫当前块中符合它要求的边((ale A_q且 ble B_q))加入并查集中,得到答案后就把当前块的这几条边撤回。每做完一个块就把它和之前的块按b归并排序。
    可能讲的不大清楚,懂了大致意思后可以自己继续想一想细节问题。

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #include<vector>
    #include<ctime>
    #define P puts("lala")
    #define cp cerr<<"lala"<<endl
    #define fi first
    #define se second
    #define ln putchar('
    ')
    #define pb push_back
    #define shmem(x) cerr<<sizeof(x)/(1024*1024.0)<<"MB"<<endl
    using namespace std;
    inline int read()
    {
        char ch=getchar();int g=1,re=0;
        while(ch<'0'||ch>'9'){if(ch=='-')g=-1; ch=getchar();}
        while(ch<='9'&&ch>='0') re=(re<<1)+(re<<3)+(ch^48),ch=getchar();
        return re*g;
    }
    typedef long long ll;
    typedef pair<int,int> pii;
    
    const int N=100050;
    struct node
    {
    	int x,y,a,b,id;
    	node(int x=0,int y=0,int a=0,int b=0,int id=0):x(x),y(y),a(a),b(b),id(id) { }
    };
    inline bool operator < (node a,node b) {return a.b<b.b;}
    inline bool cmp1(node a,node b) {return a.a<b.a;}
    inline bool cmp2(node a,node b) {return a.b<b.b;}
    node e[N],q[N];
    int n,m,blosiz,bel[N],Ans[N];
    vector<node>ve[500];
    
    int fa[N];
    inline int find(int x)
    {
    	while(fa[x]!=x) x=fa[x];
    	return x;
    }
    node stk[N]; int top=0;
    int maxa[N],maxb[N],siz[N];
    inline void merge(int x,int y,int a,int b)
    {
    	x=find(x); y=find(y);
    	if(siz[x]>siz[y]) swap(x,y);
    	stk[++top]=node(x,y,maxa[y],maxb[y],siz[y]);
    	maxa[y]=max(maxa[y],max(maxa[x],a)); maxb[y]=max(maxb[y],max(maxb[x],b));
    	if(x==y) return ;
    	siz[y]+=siz[x]; fa[x]=y;
    }
    inline void undo()
    {
    	int x=stk[top].x,y=stk[top].y;
    	siz[y]=stk[top].id; maxa[y]=stk[top].a; maxb[y]=stk[top].b;
    	fa[x]=x;
    	top--;
    }
    
    node now[N],tmp[N]; int tot=0;
    void mergesort(int l,int r)
    {
    	int p1=1,p2=l,p3=1;
    	while(p1<=tot&&p2<=r)
    	{
    		if(now[p1]<e[p2]) tmp[p3]=now[p1],p1++,p3++;
    		else tmp[p3]=e[p2],p2++,p3++;
    	}
    	while(p1<=tot) tmp[p3]=now[p1],p1++,p3++;
    	while(p2<=r) tmp[p3]=e[p2],p2++,p3++;
    	tot+=r-l+1;
    	for(int i=1;i<=tot;++i) now[i]=tmp[i];
    }
    
    int main()
    {
    #ifndef ONLINE_JUDGE
    	freopen("1.in","r",stdin);freopen("1.out","w",stdout);
    #endif
    	n=read(); m=read();
    	for(int i=1;i<=m;++i) 
    		e[i].x=read(),e[i].y=read(),e[i].a=read(),e[i].b=read();
    	int Q=read();
    	for(int i=1;i<=Q;++i) 
    		q[i].x=read(),q[i].y=read(),q[i].a=read(),q[i].b=read(),q[i].id=i;
    	
    	sort(e+1,e+1+m,cmp1);
    	blosiz=sqrt(m);
    	for(int i=1;i<=m;++i) bel[i]=(i-1)/blosiz+1;
    
    	sort(q+1,q+1+Q,cmp1);
    	for(int i=1,p1=1;i<=m;++i)
    	{
    		while(p1<=Q&&(q[p1].a<e[i].a||i==m)) ve[bel[i]].pb(q[p1]),p1++;
    	}
    	for(int i=1;i<=bel[m];++i) sort(ve[i].begin(),ve[i].end());
    	for(int i=1;i<=bel[m];++i) sort(e+(i-1)*blosiz+1,e+min(i*blosiz,m)+1);
    
    	for(int o=1;o<=bel[m];++o)
    	{
    		top=0;
    		for(int i=1;i<=n;++i) fa[i]=i,maxa[i]=maxb[i]=-1,siz[i]=1;
    		int siz=ve[o].size(),p1=1;
    		for(int w=0;w<siz;++w)
    		{
    			while(p1<=tot&&ve[o][w].b>=now[p1].b) //in front of the block
    				merge(now[p1].x,now[p1].y,now[p1].a,now[p1].b),p1++;
    			int last=top;
    			for(int i=(o-1)*blosiz+1;i<=m&&i<=o*blosiz;++i) //in the block
    				if(e[i].b<=ve[o][w].b)
    				{
    					if(e[i].a<=ve[o][w].a)
    						merge(e[i].x,e[i].y,e[i].a,e[i].b);
    				}
    				else break;
    			int r1=find(ve[o][w].x),r2=find(ve[o][w].y);
    			if(r1==r2&&maxa[r1]==ve[o][w].a&&maxb[r1]==ve[o][w].b)
    				Ans[ve[o][w].id]=1;
    			while(top!=last) undo();
    		}
    		mergesort((o-1)*blosiz+1,min(o*blosiz,m));
    	}
    	for(int i=1;i<=Q;++i) puts(Ans[i]==1?"Yes":"No");
    	return 0;
    }
    
  • 相关阅读:
    UNIX网络编程——非阻塞connect
    UNIX网络编程——非阻塞式I/O(套接字)
    UNIX网络编程——使用select 实现套接字I/O超时
    UNIX网络编程——设置套接字超时
    UNIX网络编程——名字与地址转换(gethostbyname,gethostbyaddr,getservbyname,getservbyport,getaddrinfo,getnameinfo函数)
    [Java] Java API文档下载方法
    [Selenium] 在Grid模式下打印出当前Case是在哪台Node上运行
    [Selenium] 针对下拉菜单出现之后又立马消失的问题,通过Javascript改变元素的可见属性
    [Java] 通过XPath获取XML中某个节点的属性
    [Java] 获取当前Project所在的路径
  • 原文地址:https://www.cnblogs.com/thkkk/p/8593060.html
Copyright © 2011-2022 走看看