• BZOJ5415:[NOI2018]归程(可持久化并查集,最短路)


    Description

    Input

    Output

    Sample Input1

    1
    4 3
    1 2 50 1
    2 3 100 2
    3 4 50 1
    5 0 2
    3 0
    2 1
    4 1
    3 1
    3 2

    Sample Output1

    0
    50
    200
    50
    150

    Sample Input2

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

    Sample Output2

    0
    2
    3
    1

    HINT

    Solution

    会了可持久化并查集这题可能会被卡的正解就很好写了……

    把边按高度大小从大到小加入,用可持久化并查集记下每一个时刻并查集的联通情况,

    同时用持久化的$Min[i]$数组记录$i$点所在的连通块内到点$1$的最近距离。查询的时候二分到对应时刻的并查集直接查询就行了。

    Code

      1 #include<iostream>
      2 #include<cstring>
      3 #include<cstdio>
      4 #include<queue>
      5 #include<algorithm>
      6 #define N (200009)
      7 using namespace std;
      8 
      9 struct Edge{int to,next,len;}edge[N<<2];
     10 struct Sgt{int ls,rs,v;};
     11 struct Line
     12 {
     13     int u,v,w,h;
     14     bool operator < (const Line &a) const {return h>a.h;}
     15 }l[N<<1];
     16 struct Node
     17 {
     18     int num,dis;
     19     bool operator < (const Node &a) const {return dis>a.dis;}
     20 };
     21 int T,n,m,u,v,w,h,q,k,s,v0,p0,ans;
     22 int dis[N],head[N],num_edge;
     23 bool vis[N];
     24 priority_queue<Node>Q;
     25 
     26 struct Chairman_Tree
     27 {
     28     Sgt a[N*40];
     29     int sgt_num,b[N],Root[N<<1];
     30     
     31     int Build(int l,int r)
     32     {
     33         int now=++sgt_num;
     34         if (l==r) {a[now].v=b[l]; return now;}
     35         int mid=(l+r)>>1;
     36         a[now].ls=Build(l,mid);
     37         a[now].rs=Build(mid+1,r);
     38         return now;
     39     }
     40     int Update(int pre,int l,int r,int x,int v)
     41     {
     42         int now=++sgt_num;
     43         a[now].ls=a[pre].ls;
     44         a[now].rs=a[pre].rs;
     45         if (l==r) {a[now].v=v; return now;}
     46         int mid=(l+r)>>1;
     47         if (x<=mid) a[now].ls=Update(a[now].ls,l,mid,x,v);
     48         else a[now].rs=Update(a[now].rs,mid+1,r,x,v);
     49         return now;
     50     }
     51     int Query(int now,int l,int r,int x)
     52     {
     53         if (l==r) return a[now].v;
     54         int mid=(l+r)>>1;
     55         if (x<=mid) return Query(a[now].ls,l,mid,x);
     56         else return Query(a[now].rs,mid+1,r,x);
     57     }
     58 }Fa,Dep,Min;
     59 
     60 inline int read()
     61 {
     62     int x=0; char c=getchar();
     63     while (c<'0' || c>'9') c=getchar();
     64     while (c>='0' && c<='9') x=x*10+c-'0', c=getchar();
     65     return x;
     66 }
     67 
     68 void add(int u,int v,int w)
     69 {
     70     edge[++num_edge].to=v;
     71     edge[num_edge].next=head[u];
     72     edge[num_edge].len=w;
     73     head[u]=num_edge;
     74 }
     75 
     76 int Find(int x,int t)
     77 {
     78     int fa=Fa.Query(Fa.Root[t],1,n,x);
     79     return x==fa?x:Find(fa,t);
     80 }
     81 
     82 void Dijkstra(int s)
     83 {
     84     memset(dis,0x7f,sizeof(dis));
     85     memset(vis,0,sizeof(vis));
     86     dis[s]=0;
     87     Q.push((Node){s,0});
     88     while (!Q.empty())
     89     {
     90         int x=Q.top().num; Q.pop();
     91         if (vis[x]) continue; vis[x]=1;
     92         for (int i=head[x]; i; i=edge[i].next)
     93             if (!vis[edge[i].to] && dis[x]+edge[i].len<dis[edge[i].to])
     94             {
     95                 dis[edge[i].to]=dis[x]+edge[i].len;
     96                 Q.push((Node){edge[i].to,dis[edge[i].to]});
     97             }
     98     }
     99 }
    100 
    101 int main()
    102 {
    103     T=read();
    104     while (T--)
    105     {
    106         Fa.sgt_num=Dep.sgt_num=Min.sgt_num=0;
    107         memset(head,0,sizeof(head)); num_edge=0;
    108         ans=0;
    109         n=read(); m=read();
    110         for (int i=1; i<=m; ++i)
    111         {
    112             u=read(); v=read(); w=read(); h=read();
    113             l[i]=(Line){u,v,w,h};
    114             add(u,v,w); add(v,u,w);
    115         }
    116         Dijkstra(1);
    117         sort(l+1,l+m+1);
    118         for (int i=1; i<=n; ++i)
    119             Fa.b[i]=i, Dep.b[i]=1, Min.b[i]=dis[i];
    120         Fa.Root[0]=Fa.Build(1,n);;
    121         Dep.Root[0]=Dep.Build(1,n);
    122         Min.Root[0]=Min.Build(1,n);
    123         for (int i=1; i<=m; ++i)
    124         {
    125             Fa.Root[i]=Fa.Root[i-1];
    126             Dep.Root[i]=Dep.Root[i-1];
    127             Min.Root[i]=Min.Root[i-1];
    128             int fx=Find(l[i].u,i),fy=Find(l[i].v,i);
    129             if (fx==fy) continue;
    130             int dfx=Dep.Query(Dep.Root[i],1,n,fx);
    131             int dfy=Dep.Query(Dep.Root[i],1,n,fy);
    132             if (dfx>dfy) swap(fx,fy);
    133             Fa.Root[i]=Fa.Update(Fa.Root[i],1,n,fx,fy);
    134             int d1=Min.Query(Min.Root[i],1,n,fx);
    135             int d2=Min.Query(Min.Root[i],1,n,fy);
    136             Min.Root[i]=Min.Update(Min.Root[i],1,n,fy,min(d1,d2));
    137             if (dfx==dfy) Dep.Root[i]=Dep.Update(Dep.Root[i],1,n,fy,dfy+1);
    138         }
    139         q=read(); k=read(); s=read();
    140         for (int i=1; i<=q; ++i)
    141         {
    142             v0=read(); p0=read();
    143             v0=(v0+k*ans-1)%n+1;
    144             p0=(p0+k*ans)%(s+1);
    145             int L=1,R=m,A=-1;
    146             while (L<=R)
    147             {
    148                 int mid=(L+R)>>1;
    149                 if (l[mid].h>p0) A=mid,L=mid+1;
    150                 else R=mid-1;
    151             }
    152             if (A==-1)
    153             {
    154                 printf("%d
    ",dis[v0]);
    155                 ans=dis[v0]; continue;
    156             }
    157             int fx=Find(v0,A);
    158             ans=Min.Query(Min.Root[A],1,n,fx);
    159             printf("%d
    ",ans);
    160         }
    161     }
    162 }
  • 相关阅读:
    2019省赛训练组队赛4.9周二 2017浙江省赛
    #Leetcode# 49. Group Anagrams
    #Leetcode# 57. Insert Interval
    POJ 2195 Going Home
    HDU 2255 奔小康赚大钱
    HDU 1083 Courses
    HDU 2063 过山车
    POJ 3041 Asteroids
    指针的妙处
    jzoj 6273. 2019.8.4【NOIP提高组A】欠钱 (money)
  • 原文地址:https://www.cnblogs.com/refun/p/10232403.html
Copyright © 2020-2023  润新知