• cf 786B. Legacy(线段树区间建图)


    题目链接:传送门

    题目思路:

      直接暴力连边,显然会超时,那么可以采用“源点”的建图思想,对于区间问题,可以利用线段树建图。

      建立一颗 inTree 和 outTree ,得:

      

         这样建图能保证初始时刻 [1,1] 可以到达 [1,2] ,[1,4] ,但是不能到达 其他叶子节点。

         对于区间 连接 单点,则从inTree 的区间 连接至outTree的单点;对于单点 连接 区间 则从inTree 的单点 连接至 outTree的区间 ;

         对于区间 连接 区间,则可以从 outTree 处理出来区间对应的节点集合,然后再 在inTree 中对应的区间 对集合中的点进行连边(也可以先处理inTree ,在outTree 中连边);

    代码:(下面代码中,叶子节点是两棵树复用的)

      1 #include<bits/stdc++.h>
      2 #pragma GCC optimize(2)
      3 using namespace std;
      4 typedef long long LL;
      5 typedef unsigned long long uLL;
      6 typedef pair<int,int> pii;
      7 typedef pair<LL,LL> pLL;
      8 typedef pair<double,double> pdd;
      9 const int N=1e5+5;
     10 const int M=8e5+5;
     11 const LL inf=1e16;
     12 const LL mod=1e8+7;
     13 const double eps=1e-8;
     14 const long double pi=acos(-1.0L);
     15 #define ls (i<<1)
     16 #define rs (i<<1|1)
     17 #define fi first
     18 #define se second
     19 #define pb push_back
     20 #define eb emplace_back
     21 #define mk make_pair
     22 #define mem(a,b) memset(a,b,sizeof(a))
     23 LL read()
     24 {
     25     LL x=0,t=1;
     26     char ch;
     27     while(!isdigit(ch=getchar())) if(ch=='-') t=-1;
     28     while(isdigit(ch)){ x=10*x+ch-'0'; ch=getchar(); }
     29     return x*t;
     30 
     31 }
     32 LL dis[N<<3];
     33 int cnt,vis[N<<3],n,s,q;
     34 struct node{ int l,r; };
     35 struct disx{
     36     LL x;int y;
     37     friend bool operator < (disx X,disx Y)
     38     {
     39         return X.x>Y.x;
     40     }
     41 };
     42 node c[N<<3];
     43 vector<pii> e[N<<3];
     44 inline void add(int u,int v,int w)
     45 {
     46     e[u].eb(v,w);
     47 }
     48 void buildin(int &now,int l,int r)
     49 {
     50     if(l==r) return (void)(now=l);
     51     now=++cnt;//printf("in = %d, %d %d
    ",now,l,r);
     52     c[now].l=c[now].r=0;
     53     int mid=l+r>>1;
     54     buildin(c[now].l,l,mid);
     55     buildin(c[now].r,mid+1,r);
     56     add(c[now].l,now,0);
     57     add(c[now].r,now,0);
     58 }
     59 void buildout(int &now,int l,int r)
     60 {
     61     if(l==r) return (void)(now=l);
     62     now=++cnt;//printf("out = %d, %d %d
    ",now,l,r);
     63     c[now].l=c[now].r=0;
     64     int mid=l+r>>1;
     65     buildout(c[now].l,l,mid);
     66     buildout(c[now].r,mid+1,r);
     67     add(now,c[now].l,0);
     68     add(now,c[now].r,0);
     69 }
     70 void updin(int now,int l,int r,int ll,int rr,int x,int y)
     71 {
     72     if(ll<=l&&r<=rr) return add(now,x,y);
     73     int mid=l+r>>1;
     74     if(mid>=ll) updin(c[now].l,l,mid,ll,rr,x,y);
     75     if(mid<rr) updin(c[now].r,mid+1,r,ll,rr,x,y);
     76 }
     77 void updout(int now,int l,int r,int ll,int rr,int x,int y)
     78 {
     79     if(ll<=l&&r<=rr) return add(x,now,y);
     80     int mid=l+r>>1;
     81     if(mid>=ll) updout(c[now].l,l,mid,ll,rr,x,y);
     82     if(mid<rr) updout(c[now].r,mid+1,r,ll,rr,x,y);
     83 }
     84 void dijk()
     85 {
     86     priority_queue<disx> q;
     87     for(int i=1;i<=cnt;i++) dis[i]=inf;
     88     q.push(disx{dis[s]=0,s});
     89     while(!q.empty())
     90     {
     91         int u=q.top().y;
     92         q.pop();
     93         if(vis[u]) continue;     //printf("u = %d
    ",u);
     94         vis[u]=1;
     95         for(auto x:e[u])
     96         {
     97             //printf("%d -> %d
    ",u,x.fi);
     98             int v=x.fi,w=x.se;
     99             if(dis[v]>dis[u]+w) q.push(disx{dis[v]=dis[u]+w,v});
    100         }
    101     }
    102 }
    103 int main()
    104 {
    105     n=read(),q=read(),s=read();
    106     cnt=n;
    107     int rt1,rt2;
    108     buildin(rt1,1,n);
    109     buildout(rt2,1,n);
    110     //printf("r1 = %d , r2 = %d
     ",rt1,rt2);
    111     for(int i=1;i<=q;i++)
    112     {
    113         int t=read();
    114         if(t==1)
    115         {
    116             int v=read(),u=read(),w=read();
    117             add(v,u,w);
    118         }
    119         else if(t==2)
    120         {
    121             int v=read(),l=read(),r=read(),w=read();
    122             updout(rt2,1,n,l,r,v,w);
    123         }
    124         else
    125         {
    126             int v=read(),l=read(),r=read(),w=read();
    127             updin(rt1,1,n,l,r,v,w);
    128         }
    129     }
    130    // puts("...");
    131     dijk();
    132     for(int i=1;i<=n;i++)
    133         printf("%lld ",dis[i]==inf?-1:dis[i]);
    134     printf("
    ");
    135     return 0;
    136 }
    View Code
  • 相关阅读:
    文件读写,函数,元组和集合
    Python列表,字典和字符串操作
    linux grep程序输出 文本过滤
    prj坐标转换
    ubuntu 分卷解压中文乱码
    利用ssh 删除远程服务器文件
    git 提交
    linux 命令scp
    osgEarth编译——以VS2012为例
    GDAL2.0编译——32位和64位
  • 原文地址:https://www.cnblogs.com/DeepJay/p/13942252.html
Copyright © 2020-2023  润新知