zoukankan      html  css  js  c++  java
  • 【NOIp2016】天天爱跑步

    题面

    https://www.luogu.org/problem/P1600

    题解

    树链剖分$+$对每条重链分治$+$桶。

    注意:树链剖分求$LCA$,跳矮(重链顶端的高矮)返高。

    #include<vector>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define ri register int
    #define N 300000
    using namespace std;
    
    inline int read() {
        int ret=0,f=0;char ch=getchar();
        while (ch<'0' || ch>'9') f|=(ch=='-'),ch=getchar();
        while (ch>='0' && ch<='9') ret*=10,ret+=ch-'0',ch=getchar();
        return f?-ret:ret;
    }
    
    int siz[N],top[N],p[N],cnt,dep[N],fa[N],ans[N];
    vector<int> to[N];
    int n,m,w[N];
    
    void dfs_1(int x,int ff) {
        fa[x]=ff; dep[x]=dep[ff]+1;
        siz[x]=1;
        for (ri i=0;i<to[x].size();i++) {
            int y=to[x][i]; if (y==ff) continue;
            dfs_1(y,x);
            siz[x]+=siz[y];
        }
    }
    
    void dfs_2(int x,int ff,int ctop) {
        int md=0,hs=-1;
        p[x]=++cnt; top[x]=ctop;
        for (ri i=0;i<to[x].size();i++) {
            int y=to[x][i]; if (y==ff) continue;
            if (siz[y]>md) md=siz[y],hs=y;
        }
        if (hs!=-1) dfs_2(hs,x,ctop);
        for (ri i=0;i<to[x].size();i++) {
            int y=to[x][i]; if (y==ff || y==hs) continue;
            dfs_2(y,x,y);
        }
    }
    
    int lca(int x,int y) {
        while (top[x]^top[y]) {
            if (dep[top[x]]>dep[top[y]]) x=fa[top[x]]; else y=fa[top[y]];
        }
        if (dep[x]<dep[y]) return x; else return y;
    }
    
    struct node {
        int v,p,top,id;
        bool operator < (const node &rhs) const {
          if (top!=rhs.top) return top<rhs.top;
          if (v!=rhs.v) return v<rhs.v;
          if (p!=rhs.p) return p<rhs.p;
          return 0;
        }
    } up[N],dw[N];
    
    int sup[N],sdw[N];
    
    void count_up(int t,int lp,int rp,int v) {
        int a=lower_bound(up+1,up+n+1,(node){v,lp,t,-1})-up;
        int b=upper_bound(up+1,up+n+1,(node){v,rp,t,-1})-up;
        sup[a]++; sup[b]--;
    }
    
    void count_dw(int t,int lp,int rp,int v) {
        int a=lower_bound(dw+1,dw+n+1,(node){v,lp,t,-1})-dw;
        int b=upper_bound(dw+1,dw+n+1,(node){v,rp,t,-1})-dw;
        sdw[a]++; sdw[b]--;
    }
    
    int main() {
        
        n=read(); m=read();
        for (ri i=1;i<n;i++) {
            int u=read(),v=read();
            to[u].push_back(v);
            to[v].push_back(u);
        }
        dfs_1(1,0);
        dfs_2(1,0,1);
        for (ri i=1;i<=n;i++) w[i]=read();
        for (ri i=1;i<=n;i++) {
            up[p[i]]=(node){dep[i]+w[i],p[i],top[i],i};
            dw[p[i]]=(node){dep[i]-w[i],p[i],top[i],i};
        }
        
        sort(up+1,up+n+1);
        sort(dw+1,dw+n+1);
        
        for (ri i=1;i<=m;i++) {
            int s=read(),t=read();
            int x=lca(s,t);
            int vid=dep[s],vid2=dep[t]-(dep[s]+dep[t]-2*dep[x]);
            while (1) {
                if (dep[top[s]]>dep[x]) count_up(top[s],p[top[s]],p[s],vid),s=fa[top[s]];
                else {count_up(top[s],p[x],p[s],vid); break;}
            }
            while (1) {
                if (dep[top[t]]>dep[x]+1) count_dw(top[t],p[top[t]],p[t],vid2),t=fa[top[t]];
                else {count_dw(top[t],p[t]-(dep[t]-(dep[x]+1)),p[t],vid2); break;}
            }
        }
        
        for (ri i=1;i<=n;i++) {
            sup[i]+=sup[i-1]; ans[up[i].id]+=sup[i];
            sdw[i]+=sdw[i-1]; ans[dw[i].id]+=sdw[i];
        }
        
        for (ri i=1;i<=n;i++) printf("%d ",ans[i]);
        return 0;
    }
  • 相关阅读:
    iphone 越狱后 安装 pillow 报错 (未解决, 仅记录)
    阿甘正传影评
    聊聊“内卷”的本质
    Django REST Framework: 使用cach_page和drf-extensions进行缓存
    Python常用第三方库大全
    Go 第三方库推荐:类型转换如此简单
    Python 内置库:itertools
    4 款 MySQL 调优工具
    如何使用 asyncio 限制协程的并发数
    Go 的json 解析标准库竟然存在这样的陷阱?
  • 原文地址:https://www.cnblogs.com/shxnb666/p/11826437.html
Copyright © 2011-2022 走看看