zoukankan      html  css  js  c++  java
  • 【BZOJ3073】[Pa2011]Journeys 线段树+堆优化Dijkstra

    【BZOJ3073】[Pa2011]Journeys

    Description

    Seter建造了一个很大的星球,他准备建造N个国家和无数双向道路。N个国家很快建造好了,用1..N编号,但是他发现道路实在太多了,他要一条条建简直是不可能的!于是他以如下方式建造道路:(a,b),(c,d)表示,对于任意两个国家x,y,如果a<=x<=b,c<=y<=d,那么在xy之间建造一条道路。Seter保证一条道路不会修建两次,也保证不会有一个国家与自己之间有道路。
    Seter好不容易建好了所有道路,他现在在位于P号的首都。Seter想知道P号国家到任意一个国家最少需要经过几条道路。当然,Seter保证P号国家能到任意一个国家。
    注意:可能有重边

    Input

    第一行三个数N,M,P。N<=500000,M<=100000。
    后M行,每行4个数A,B,C,D。1<=A<=B<=N,1<=C<=D<=N。

    Output

    N行,第i行表示P号国家到第i个国家最少需要经过几条路。显然第P行应该是0。

    Sample Input

    5 3 4
    1 2 4 5
    5 5 4 4
    1 1 3 3

    Sample Output

    1
    1
    2
    0
    1

    题解:珍爱生命,远离vector!珍爱生命,远离cfree!

    ZZ一上午就跟这道题耗上了,一开始想用线段树维护一堆vector,然后用并查集+BFS来搞,结果就死在了vector的删除操作上啊~,各种奇葩错误信息直接将cfree搞炸了,然后卸载+重启+重装了n次也不好使,于是默默回归gdb。。。

    于是最后还是放弃,学了用线段树优化建图+Dijkstra,具体方法:

    建立两棵线段树,A树从所有节点向父亲连边,B树从所有节点向儿子连边,从B树的所有叶子向A树的所有叶子连边,边权都是0。

    对于每个操作,新建节点c,从A中对应的节点向c连边,从c向B中对应节点连边,边权都是${1over2}$

    然后跑Dijkstra就行了。

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <queue>
    #include <utility>
    #define mp(A,B)	make_pair(A,B)
    #define lson (x<<1)
    #define rson (x<<1|1)
    using namespace std;
    const int maxn=500010;
    typedef pair<int,int> pii;
    int n,m,S,tot,cnt;
    int vis[5000000],dis[5000000],pos[maxn];
    int to[30000000],next[30000000],val[30000000],head[5000000];
    priority_queue<pii> pq;
    int rd()
    {
    	int ret=0,f=1;	char gc=getchar();
    	while(gc<'0'||gc>'9')	{if(gc=='-')f=-f;	gc=getchar();}
    	while(gc>='0'&&gc<='9')	ret=ret*10+gc-'0',gc=getchar();
    	return ret*f;
    }
    void add(int a,int b,int c)
    {
    	to[cnt]=b,val[cnt]=c,next[cnt]=head[a],head[a]=cnt++;
    }
    struct sag
    {
    	void build(int l,int r,int x,int flag)
    	{
    		if(l==r)
    		{
    			if(!flag)	pos[l]=x;
    			else	add(x+4*n,x,0);
    			return ;
    		}
    		int mid=l+r>>1;
    		build(l,mid,lson,flag),build(mid+1,r,rson,flag);
    		if(flag)	add(x+4*n,lson+4*n,0),add(x+4*n,rson+4*n,0);
    		else	add(lson,x,0),add(rson,x,0);
    	}
    	void updata(int l,int r,int x,int a,int b,int c,int flag)
    	{
    		if(a<=l&&r<=b)
    		{
    			if(!flag)	add(x,c,1);
    			else	add(c,x+4*n,1);
    			return ;
    		}
    		int mid=l+r>>1;
    		if(a<=mid)	updata(l,mid,lson,a,b,c,flag);
    		if(b>mid)	updata(mid+1,r,rson,a,b,c,flag);
    	}
    }s1,s2;
    int main()
    {
    	n=rd(),m=rd(),S=rd();
    	int i,a,b,c,d;
    	memset(head,-1,sizeof(head));
    	s1.build(1,n,1,0),s2.build(1,n,1,1);
    	tot=n<<3;
    	for(i=1;i<=m;i++)
    	{
    		a=rd(),b=rd(),c=rd(),d=rd();
    		s1.updata(1,n,1,a,b,++tot,0),s2.updata(1,n,1,c,d,tot,1);
    		s1.updata(1,n,1,c,d,++tot,0),s2.updata(1,n,1,a,b,tot,1);
    	}
    	memset(dis,0x3f,sizeof(dis));
    	pq.push(mp(0,pos[S])),dis[pos[S]]=0;
    	int u;
    	while(!pq.empty())
    	{
    		u=pq.top().second,pq.pop();
    		if(vis[u])	continue;
    		vis[u]=1;
    		for(i=head[u];i!=-1;i=next[i])
    			if(dis[to[i]]>dis[u]+val[i])
    				dis[to[i]]=dis[u]+val[i],pq.push(mp(-dis[to[i]],to[i]));
    	}
    	for(i=1;i<=n;i++)	printf("%d
    ",dis[pos[i]]>>1);
    	return 0;
    }

     

  • 相关阅读:
    C#在窗口中ComboBox控件中加载数据库数据
    C#登录窗口(访问数据库)的制作,类文件的制作及使用
    C#通过窗体应用程序操作数据库(增删改查)
    C#在listview控件中显示数据库数据
    C#窗体与sql数据库的连接
    C#记事本的制作
    C#计算器的制作
    C#委托的初步理解
    使用Java语言开发微信公众平台(七)——音乐消息的回复
    使用Java语言开发微信公众平台(六)——获取access_token
  • 原文地址:https://www.cnblogs.com/CQzhangyu/p/7016611.html
Copyright © 2011-2022 走看看