zoukankan      html  css  js  c++  java
  • NOI2018归程

    • 题意 ->here

    • solution

    前置技能:kruskal重构树

    我们把边按海拔从大到小排序,建立kruskal重构树,这样对于一个点x,设x海拔为h[x],当天水位为h0,那么如果有h[x]>h0,则以x为根的子树内所有节点的海拔都大于h0,即整个子树都可以通过车到达

    于是我们跑一遍最短路,对于一个出发点v0,找到v0的祖先中深度最小且满足海拔大于h0的点fa,以fa为根的子树内离点1最近点的距离即为答案

    找到fa->倍增暴力跳

    找出最近距离->dfs扫一遍

    ->solved

    • code 不忍直视的码风

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<queue>
    #define fi first
    #define se second
    #define mk(a,b) make_pair(a,b)
    #define pi pair<int,int>
    #define N 200005
    #define M 600005
    using namespace std;
    
    struct sett{
        int u,v,w,h;
        friend bool operator<(const sett &a,const sett &b){
            return a.h>b.h;
        }
    }lib[M];
    struct zero{
        int nxt,to,dis;
    }edge[M<<1];
    int head[N<<1],tot=0;
    void add_edge(int a,int b,int c){edge[++tot]=(zero){head[a],b,c};head[a]=tot;}
    
    int dis[N],f[N<<1],fa[22][N<<1],kl[N<<1],res[N<<1];
    bool vis[N];
    int n,m,q,type,s;
    
    int find(int k){return (f[k]==k)?k:f[k]=find(f[k]);}
    
    void dijkstra(){
        priority_queue<pi,vector<pi>,greater<pi> > q;
        memset(dis,0X3f,sizeof dis),memset(vis,0,sizeof vis);
        dis[1]=0;q.push(mk(0,1));
        while(!q.empty()){
            pi now=q.top();
            q.pop();
            if(vis[now.se])continue;
            vis[now.se]=1;
            for(int i=head[now.se];i;i=edge[i].nxt){
                int to=edge[i].to;
                if(dis[to]>now.fi+edge[i].dis){
                    dis[to]=now.fi+edge[i].dis;
                    if(!vis[to])q.push(mk(dis[to],to));
                }
            }
        }
    }
    int dfs(int x){
        if(!head[x])return res[x]=dis[x];
        res[x]=998244353;
        for(int i=head[x];i;i=edge[i].nxt){
            int to=edge[i].to;
            res[x]=min(res[x],dfs(to));
        }
        return res[x];
    }
    void kruskal(){
        int tp=n;
        sort(lib+1,lib+m+1);
        for(int i=1;i<=n;i++)f[i]=i;
        for(int i=1;i<=m;i++){
            int u=find(lib[i].u),v=find(lib[i].v),h=lib[i].h;
            if(u==v)continue;
            tp++;kl[tp]=h;f[u]=f[v]=f[tp]=tp;fa[0][u]=fa[0][v]=tp;
            add_edge(tp,u,1),add_edge(tp,v,1);
        }
        for(int i=1;i<=20;i++)for(int r=1;r<=tp;r++)fa[i][r]=fa[i-1][fa[i-1][r]];
        dfs(tp);
    }
    int main(){
        int T;
        scanf("%d",&T);
        while(T--){
            memset(lib,0,sizeof lib),memset(edge,0,sizeof edge),memset(head,0,sizeof head),memset(fa,0,sizeof fa),memset(kl,0,sizeof kl),tot=0;
            scanf("%d%d",&n,&m);
            for(int i=1;i<=m;i++){
               int a,b,c,d;
                scanf("%d%d%d%d",&a,&b,&c,&d);
                add_edge(a,b,c),add_edge(b,a,c);
                lib[i]=(sett){a,b,c,d};
            }
            dijkstra();
            memset(edge,0,sizeof edge),memset(head,0,sizeof head),tot=0;
            syk();
            scanf("%d%d%d",&q,&type,&s);
            int lastans=0;
            while(q--){
                int pos,h;
                scanf("%d%d",&pos,&h);
                pos=(pos+type*lastans-1)%n+1,h=(h+type*lastans)%(s+1);
                for(int i=20;i>=0;i--)if(fa[i][pos]&&kl[fa[i][pos]]>h)pos=fa[i][pos];
                lastans=res[pos];
                printf("%d
    ",lastans);
            } 
        }
    }
    
  • 相关阅读:
    Python入门11 —— 基本数据类型的操作
    Win10安装7 —— 系统的优化
    Win10安装6 —— 系统的激活
    Win10安装5 —— 系统安装步骤
    Win10安装4 —— 通过BIOS进入PE
    Win10安装2 —— 版本的选择与下载
    Win10安装1 —— 引言与目录
    Win10安装3 —— U盘启动工具安装
    虚拟机 —— VMware Workstation15安装教程
    Python入门10 —— for循环
  • 原文地址:https://www.cnblogs.com/stepsys/p/11309184.html
Copyright © 2011-2022 走看看