zoukankan      html  css  js  c++  java
  • 【agc002d】Stamp Rally

    题目大意

    无向图中,每次询问从x和y分别出发,一共经过z个点,使需要走过编号最大的边最小。

    解题思路

    对于暴力,我们对于每个询问二分答案ans,将1~ans的边加入,用并查集维护,如果x和y在同一个并查集,则判断该并查集大小是否大于等于z,否则判断该x所在并查集和y所在并查集大小的和是否大于等于z。
    考虑如何优化,整体二分,二分边的编号,同时对于每个编号区间[l,r],记录一个询问集合,表示该集合的询问的答案在区间[l,r]中。同时用可撤销并查集维护。

    #include <cmath>
    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <algorithm>
    #include <queue>
    #include <map>
    #include <bitset>
    #include <set>
    const int maxlongint=2147483647;
    const int mo=1e9+7;	
    const int N=100005;
    using namespace std;
    struct arr
    {
    	int x,y,z,p;
    }ask[N],out[N];
    int n,m,q,a[N][2],ans[N],fa[N],val[N],t[N],size[N],tv[N];
    int get(int x)
    {
    	return x==fa[x]?x:get(fa[x]);
    }
    void mesh(int x,int y)
    {
    	int xx=get(x),yy=get(y);
    	if(xx==yy) return;
    	if(val[xx]>val[yy]) fa[yy]=xx,t[++t[0]]=yy,size[xx]+=size[yy],tv[t[0]]=val[xx];
    	else
    	{
    		fa[xx]=yy,t[++t[0]]=xx,size[yy]+=size[xx];
    		tv[t[0]]=val[yy];
    		if(val[xx]==val[yy]) val[yy]++;
    	}
    }
    void del()
    {
    	int x=t[t[0]];
    	size[fa[x]]-=size[x],val[fa[x]]=tv[t[0]];
    	fa[x]=x;
    	t[0]--; 
    }
    void dc(int l,int r,int L,int R)
    {
    	if(L>R) return;
    	if(l==r)
    	{
    		for(int i=L;i<=R;i++) ans[ask[i].p]=l;
    		return;
    	}
    	int mid=(l+r)>>1,mm=L-1,sign=t[0];
    	for(int i=l;i<=mid;i++) mesh(a[i][0],a[i][1]);
    	for(int i=L;i<=R;i++)
    	{
    		int xx=get(ask[i].x),yy=get(ask[i].y),vv=(xx==yy?size[xx]:size[xx]+size[yy]);
    		if(vv>=ask[i].z) swap(ask[i],ask[++mm]);
    	}
    	dc(mid+1,r,mm+1,R);
    	for(;t[0]>sign;del());
    	dc(l,mid,L,mm);
    }
    int main()
    {
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<=m;i++) scanf("%d%d",&a[i][0],&a[i][1]);
    	scanf("%d",&q);
    	for(int i=1;i<=q;i++) scanf("%d%d%d",&ask[i].x,&ask[i].y,&ask[i].z),ask[i].p=i;
    	for(int i=1;i<=n;i++) fa[i]=i,size[i]=1;
    	dc(1,m,1,q);
    	for(int i=1;i<=q;i++) printf("%d
    ",ans[i]);
    }
    
  • 相关阅读:
    rapidjson 使用
    【设计模式】模板方法模式
    【设计模式】策略模式
    【设计模式】建造者模式
    【设计模式】享元模式
    /dev/sda1 contains a file system with errors,check forced.
    如何编写高效的Python的代码
    VsCode 调试 Python 代码
    Python 使用 pyinstaller 打包 代码
    初次使用git上传代码到github远程仓库
  • 原文地址:https://www.cnblogs.com/chen1352/p/9099501.html
Copyright © 2011-2022 走看看