• la4730(并查集+树状数组)


    https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&category=30&page=show_problem&problem=2731

    题意:有t组测试数据,第一个是n,代表有n个城市,标号为0~~n-1,接下来的n行,依次是标号为0~~n-1个城市的坐标,然后有m个操作,road操作代表着将两个点联通,line操作代表询问,直线y=c穿过多少个州,这些州总共有多少个城市。州就是有两个及以上的城市联通所形成的东西........

    思路:我的初始思路是用并查集先链接起来,并且设置固定的根节点,并维护它们......想了好久,发现实现起来,非常困难。看《训练指南》上的思路,是用并查集把点连接起来,再把他们按照y坐标来更新.......具体思路是用到了树状数组的成段更新,单点查询......值得注意的地方,就是直线y=c中,c一定是一个带0.5小数的实数。这样的话,我们可以将它的小数部分去掉,但同时,在树状数组更新的时候,最顶端部分,我们要可以不去更新.......其他的看代码吧

    代码很好看懂,就是用并查集来查询两个城市是否联通,联通的话,不管,否则,就开始更新,把原来所在区域的的州减去,州所附带的城市减去,然后把两个州合并成一个州,再将新形成的州和它所附带的城市加入所在区域。

    #include<iostream>
    #include<stdio.h>
    #include<string.h>
    using namespace std;
    #define min(x,y)  x>y? y:x
    #define max(x,y)  x>y? x:y
    int c[1000006][2],maxn;
    struct node
    {
    	int zx;
    	int zd;
    	int ans;
    	int father;
    }t[100005];
    int find(int x)
    {
    	int root,i=x;
    	while(x!=t[x].father)
    	x=t[x].father;
    	root=x;
    	x=i;
    	while(x!=t[x].father)
    	{
    		i=t[x].father;
    		t[x].father=root;
    		x=i;
    	}
    	return root;
    }
    int lowbit(int x)
    {
    	return x&(-x);
    }
    void updata(int x,int y,int k)
    {
    	for(int i=x;i<=maxn;i+=lowbit(i))
    	{
    		c[i][y]+=k;
    	}
    }
    int getsum(int x,int y)
    {
    	int sum=0;
    	for(int i=x;i>0;i-=lowbit(i))
    	{
    		sum+=c[i][y];
    	}
    	return sum;
    }
    int main()
    {
    	int text;
    	scanf("%d",&text);
    	while(text--)
    	{
    		int n;
    		scanf("%d",&n);
    		memset(c,0,sizeof(c));
    		//for(int i=0;i<100005;i++)
    		//t[i].father=i;
    		maxn=0;
    		for(int i=0;i<n;i++)
    		{
    			int x,y;
    			scanf("%d%d",&x,&y);
    			y++;
    			t[i].father=i;
    			t[i].zx=t[i].zd=y;
    			t[i].ans=1;
    			if(maxn<y)
    			maxn=y;
    		}
    		int m;
    		scanf("%d",&m);
    		while(m--)
    		{
    			char ch[10];
    			scanf("%s",ch);
    			if(ch[0]=='r')
    			{
    				int tmp,tmp1;
    				scanf("%d%d",&tmp,&tmp1);
    				int a=find(tmp);
    				int b=find(tmp1);
    				if(a!=b)
    				{
    					updata(t[a].zx,0,-1);
    					updata(t[a].zd,0,1);
    					updata(t[a].zx,1,-t[a].ans);
    					updata(t[a].zd,1,t[a].ans);
    					updata(t[b].zx,0,-1);
    					updata(t[b].zd,0,1);
    					updata(t[b].zx,1,-t[b].ans);
    					updata(t[b].zd,1,t[b].ans);
    					if(a>b)
    					swap(a,b);
    					t[a].father=b;
    					t[b].zx=min(t[a].zx,t[b].zx);
    					t[b].zd=max(t[a].zd,t[b].zd);
    					t[b].ans+=t[a].ans;
    					updata(t[b].zx,0,1);
    					updata(t[b].zd,0,-1);
    					updata(t[b].zx,1,t[b].ans);
    					updata(t[b].zd,1,-t[b].ans);
    				}
    			}
    			else
    			{
    				double tmp;
    				scanf("%lf",&tmp);
    				int tmp1=(int)tmp+1;
    				printf("%d %d
    ",getsum(tmp1,0),getsum(tmp1,1));
    			}
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    用户模式同步之互斥体小解
    用户模式同步之信号量小解
    用户模式同步之事件小解
    中断和异常
    断点之软件断点的一些基本知识(INT3)
    部署Django项目Nginx + uwsgi
    CentOS切换root用户一直提示Incorrect password
    一张图看懂Mysql的join连接
    Nginx部署入门
    Django使用多个数据库
  • 原文地址:https://www.cnblogs.com/ziyi--caolu/p/3192666.html
Copyright © 2020-2023  润新知