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;
    }
  • 相关阅读:
    【SCOI 2011】 糖果
    【POJ 3159】 Candies
    【POJ 1716】 Integer Intervals
    【POJ 2983】 Is the information reliable?
    【POJ 1364】 King
    【POJ 1201】 Intervals
    【POJ 1804】 Brainman
    6月10日省中提高组题解
    【POJ 3352】 Road Construction
    【POJ 1144】 Network
  • 原文地址:https://www.cnblogs.com/shxnb666/p/11826437.html
Copyright © 2011-2022 走看看