• BZOJ 3073: [Pa2011]Journeys


    Description

    (n)个点,每次在([a,b])到([c,d])的点,分别连边 (nleqslant 5 imes 10^5,mleqslant 10^5).

    Solution

    最短路+线段树.

    线段树优化建图...

    建两颗线段树,从一个线段树的节点出发,到另一颗线段树对应的节点即可。

    同时把叶节点对应连起来.

    然后每次连边新建一个中间的节点,不然直接连也可以,不过那样边数是(O(nlog^2 n))的.

    Code

    /**************************************************************
        Problem: 3073
        User: BeiYu
        Language: C++
        Result: Accepted
        Time:17520 ms
        Memory:226032 kb
    ****************************************************************/
     
    #include <bits/stdc++.h>
    using namespace std;
     
    #define mid ((l+r)>>1)
    #define lc (o<<1)
    #define rc (o<<1|1)
    #define uor(i,j,k) for(int i=j;i<=(int)k;i++)
    #define uep(i,j,k) for(int i=j;i<(int)k;i++)
     
    const int N = 5005000;
     
    inline int in(int x=0,char s=getchar()) { while(s>'9'||s<'0')s=getchar();
        while(s>='0'&&s<='9')x=x*10+s-'0',s=getchar();return x; }
     
    int n,m,s,cp,B;
    int id[N],d[N],b[N];
    struct Edge { int v,w; };
    bool operator < (const Edge &a,const Edge &b) { return a.w>b.w; }
     
    vector<Edge> g[N];
    priority_queue<Edge> q;
     
    void AddEdge(int u,int v,int w) { g[u].push_back((Edge) { v,w }); }
    void Build1(int o,int l,int r) {
    //  cout<<o<<" "<<l<<" "<<r<<endl;
        if(l==r) { cp=max(cp,o);return; }
        Build1(lc,l,mid),Build1(rc,mid+1,r);
        AddEdge(lc,o,0),AddEdge(rc,o,0);
    }
    void Build2(int o,int l,int r) {
        if(l==r) { id[l]=o;return; }
        Build2(lc,l,mid),Build2(rc,mid+1,r);
        AddEdge(o+B,lc+B,0),AddEdge(o+B,rc+B,0);
    }
    void get_id(int o,int l,int r,int L,int R,vector<int> &res) {
        if(L<=l && r<=R) { res.push_back(o);return; }
        if(L<=mid) get_id(lc,l,mid,L,R,res);
        if(R>mid) get_id(rc,mid+1,r,L,R,res);
    }
    void Dijstra(int s) {
        memset(d,0x3f,sizeof(d));
        d[s]=0,q.push((Edge) { s,0 });
        for(int x;!q.empty();) {
            x=q.top().v,q.pop();
            if(b[x]) continue;b[x]=1;
            uep(i,0,g[x].size()) {
                int v=g[x][i].v,w=g[x][i].w;
                if(d[x]+w<d[v]) {
                    d[v]=d[x]+w;
                    if(!b[v]) q.push((Edge) { v,d[v] });
                }
            }
        }
    }
    void out() {
        uor(i,1,cp) {
            cout<<i<<"-->";
            uep(j,0,g[i].size()) cout<<g[i][j].v<<"("<<g[i][j].w<<")"<<" ";
            cout<<endl;
        }
    }
    int main() {
        n=in(),m=in(),s=in(),Build1(1,1,n),B=cp,cp<<=1,Build2(1,1,n);
        uor(i,1,n) AddEdge(id[i]+B,id[i],0);
        uor(i,1,m) {
            int a=in(),b=in(),c=in(),d=in(),x;
            vector<int> aa,bb;
            aa.clear(),bb.clear();
            get_id(1,1,n,a,b,aa),get_id(1,1,n,c,d,bb);
            x=++cp;
            uep(u,0,aa.size()) AddEdge(x,aa[u]+B,1);
            uep(v,0,bb.size()) AddEdge(bb[v],x,1);
            x=++cp;
            uep(v,0,bb.size()) AddEdge(x,bb[v]+B,1);
            uep(u,0,aa.size()) AddEdge(aa[u],x,1);
        }
    //  cout<<B<<" "<<cp<<endl;
    //  out();
        vector<int> tmp;tmp.clear(),get_id(1,1,n,s,s,tmp),s=tmp[0];
    //  cout<<s<<endl;
    //  uor(i,1,n) cout<<id[i]<<endl;
        Dijstra(s);
        for(int i=1;i<=n;i++) printf("%d
    ",d[id[i]]>>1);
        return 0;
    }
    

      

  • 相关阅读:
    SYSTEM32 下的几乎所有文件的简单说明
    Windows2000 下管理员账户真的不安全
    Windows2000 下管理员账户真的不安全
    SYSTEM32 下的几乎所有文件的简单说明
    看看你电脑里面有多少垃圾文件浪费内存
    巧妙利用三招保护局域网中的 IP 地址
    Sun推出OpenSolaris 为技术立异注入生机
    高质量C /C编程指南附录B :C /C试题和答案
    高质量C /C编程指南第8章 C 函数的初级特性
    俄罗斯邮政将迁徙到Linux 有关机构已入手入手测试Linux
  • 原文地址:https://www.cnblogs.com/beiyuoi/p/6804069.html
Copyright © 2020-2023  润新知