zoukankan      html  css  js  c++  java
  • LG P4768 [NOI2018] 归程

    Description

    本题的故事发生在魔力之都,在这里我们将为你介绍一些必要的设定。
    魔力之都可以抽象成一个 $n$ 个节点、$m$ 条边的无向连通图(节点的编号从 $1$ 至 $n$)。我们依次用 $l,a$ 描述一条边的**长度、海拔**。

    作为季风气候的代表城市,魔力之都时常有雨水相伴,因此道路积水总是不可避免的。由于整个城市的排水系统连通,因此**有积水的边一定是海拔相对最低的一些边**。我们用**水位线**来描述降雨的程度,它的意义是:所有海拔**不超过**水位线的边都是**有积水**的。

    Yazid 是一名来自魔力之都的 OIer,刚参加完 ION2018 的他将踏上归程,回到他温暖的家。Yazid 的家恰好在魔力之都的 $1$ 号节点。对于接下来 $Q$ 天,每一天 Yazid 都会告诉你他的出发点 $v$ ,以及当天的水位线 $p$。

    每一天,Yazid 在出发点都拥有一辆车。这辆车由于一些故障不能经过有积水的边。Yazid 可以在任意节点下车,这样接下来他就可以步行经过有积水的边。但车会被留在他下车的节点并不会再被使用。
    需要特殊说明的是,第二天车会被重置,这意味着:
    - 车会在新的出发点被准备好。
    - Yazid 不能利用之前在某处停放的车。

    Yazid 非常讨厌在雨天步行,因此他希望在完成回家这一目标的同时,最小化他**步行经过的边**的总长度。请你帮助 Yazid 进行计算。

    本题的部分测试点将强制在线,具体细节请见【输入格式】和【子任务】。

    Solution

    将边以海拔从高到低加入可持久化并查集,如果预处理出每个点到1的最短路,那么询问点连通块内最短路的最小值就是答案

    查询时二分找到在哪个线段树上

    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<queue>
    using namespace std;
    int n,m,head[200005],tot,sav[800005],T,q,K,S,dep[20000005],lc[20000005],rc[20000005],cnt,val[20000005],lasans,rt[800005];
    unsigned int dist[200005],minn[20000005];
    bool vst[200005];
    struct Edge{
        int to,nxt;
        unsigned int w;
    }edge[800005];
    struct Node{
        int u,v,a;
        bool operator <(const Node &z)const{return a<z.a;}
    }node[800005];
    struct Ele{
        unsigned int x,val;
        bool operator <(const Ele &z)const{return val>z.val;}
    };
    inline int read(){
        int w=0,f=1;
        char ch=0;
        while(ch<'0'||ch>'9'){if(ch=='-') f=-1; ch=getchar();}
        while(ch>='0'&&ch<='9')w=(w<<1)+(w<<3)+ch-'0',ch=getchar();
        return w*f;
    }
    void dijkstra(int s){
        priority_queue<Ele>q;
        q.push((Ele){s,0});
        while(q.size()){
            Ele u=q.top();
            q.pop();
            if(vst[u.x])continue;
            dist[u.x]=u.val,vst[u.x]=true;
            for(int i=head[u.x];i;i=edge[i].nxt){
                int v=edge[i].to;
                if(!vst[v])q.push((Ele){v,edge[i].w+u.val});
            }
        }
    }
    void build(int &i,int l,int r){
        if(!i)i=++cnt;
        if(l==r){val[i]=l,minn[i]=dist[l];return;}
        int mid=l+r>>1;
        build(lc[i],l,mid),build(rc[i],mid+1,r);
    }
    int ask(int i,int l,int r,int p){
        if(l==r)return i;
        int mid=l+r>>1;
        if(p<=mid)return ask(lc[i],l,mid,p);
        else return ask(rc[i],mid+1,r,p);
    }
    int find(int i,int x){
        int ret=ask(i,1,n,x);
        while(val[ret]!=x)x=val[ret],ret=ask(i,1,n,x);
        return ret;
    }
    int update(int &i,int j,int l,int r,int p){
        i=++cnt;
        if(l==r)return i;
        int mid=l+r>>1;
        lc[i]=lc[j],rc[i]=rc[j];
        if(p<=mid)return update(lc[i],lc[j],l,mid,p);
        else return update(rc[i],rc[j],mid+1,r,p);
    }
    int main(){
        for(int t=read();t;t--){
            n=read(),m=read(),cnt=tot=lasans=0,memset(head,0,sizeof(head)),memset(rt,0,sizeof(rt)),memset(minn,0,sizeof(minn)),memset(dep,0,sizeof(dep)),memset(val,0,sizeof(val)),memset(vst,false,sizeof(vst)),memset(lc,0,sizeof(lc)),memset(rc,0,sizeof(rc));
            for(int i=1;i<=m;i++){
                int u=read(),v=read(),l=read(),a=read();
                edge[++tot]=(Edge){v,head[u],l},head[u]=tot,edge[++tot]=(Edge){u,head[v],l},head[v]=tot,node[i]=(Node){u,v,a};
            }
            dijkstra(1),q=read(),K=read(),S=read(),sort(node+1,node+m+1);
            for(int i=1;i<=m;i++)sav[i]=node[i].a;
            sav[m+1]=S+1,sort(sav+1,sav+m+2),T=unique(sav+1,sav+m+2)-sav-1,build(rt[T],1,n);
            for(int i=T-1,pos=m;i;i--){
                rt[i]=rt[i+1];
                for(;pos&&node[pos].a==sav[i];pos--){
                    int u=find(rt[i],node[pos].u),v=find(rt[i],node[pos].v);
                    if(val[u]!=val[v]){
                        if(dep[u]>dep[v])swap(u,v);
                        val[update(rt[i],rt[i],1,n,val[u])]=val[v];
                        int w=update(rt[i],rt[i],1,n,val[v]);
                        val[w]=val[v],minn[w]=min(minn[u],minn[v]),dep[w]=dep[v]+(dep[u]==dep[v]);
                    }
                }
            }
            for(;q;q--){
                int u=(read()+K*lasans-1)%n+1,p=(read()+K*lasans)%(S+1);
                printf("%u
    ",lasans=minn[find(rt[upper_bound(sav+1,sav+T+1,p)-sav],u)]);
            }
        }
        return 0;
    }
    [NOI2018] 归程
  • 相关阅读:
    用Interface Builder自定义View
    UINavigationController
    pod install 失败
    关于@synchronized(self)的用法(转)
    杂记
    理解REST软件架构
    ios NSNotificationCenter消息注册与撤销
    UIApplication sharedApplication详细解释-IOS
    ios 数据持久化的三种方式
    '*.h' file not found
  • 原文地址:https://www.cnblogs.com/JDFZ-ZZ/p/14563728.html
Copyright © 2011-2022 走看看