zoukankan      html  css  js  c++  java
  • [NOIP2015]运输计划

    树剖学的好啊。。。
    先预处理出来每个询问的距离,然后二分答案,check的时候树上差分一下,求出来大于mid的询问的最长公共边,减去以后判一下行不行。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int N=300006;
    struct Edge{int to,nxt,val;}e[N<<1];
    int head[N],ecnt,n,m,fa[N],dep[N],son[N],siz[N],dis[N],dfn[N],top[N],tim,vis[N],rnk[N],cost[N];
    struct Q{int x,y,len;}q[N];
    void add(int &bg,int &ed,int &val){e[++ecnt].nxt=head[bg];e[ecnt].to=ed;e[ecnt].val=val;head[bg]=ecnt;}
    void dfs1(int x) {
      siz[x]=1;
      for(int i=head[x];i;i=e[i].nxt) {
        int v=e[i].to;
        if(v==fa[x]) continue;
        cost[v]=e[i].val;
        fa[v]=x;dep[v]=dep[x]+1;dis[v]=dis[x]+e[i].val;
        dfs1(v);
        siz[x]+=siz[v];
        if(siz[son[x]]<siz[v] ) son[x]=v;
      }
    }
    void dfs2(int x,int qtop) {
      dfn[x]=++tim;top[x]=qtop;rnk[tim]=cost[x];
      if(son[x]) dfs2(son[x],qtop);
      for(int i=head[x];i;i=e[i].nxt) {
        int v=e[i].to;
        if(v==fa[x]||v==son[x]) continue;
        dfs2(v,v);
      }
    }
    int lca(int x,int y) {
        while(top[x]!=top[y]) {
          if(dep[top[x]]<dep[top[y]]) swap(x,y);
          x=fa[top[x]];
        }
        return dep[x]<dep[y]?x:y;
    }
    bool cmp(Q x,Q y) {return x.len>y.len;}
    int f[N];
    void cf(int x,int y) {
      while(top[x]!=top[y]) {if(dep[top[x]]<dep[top[y]])swap(x,y);f[dfn[top[x]]]++,f[dfn[x]+1]--,x=fa[top[x]];}
      if(x==y) return;
      if(dep[x]>dep[y])swap(x,y);
      f[dfn[x]+1]++,f[dfn[y]+1]--;
    }
    int check(int &tim) {
      int cnt=1;
      while(q[cnt].len>tim) cnt++;
      cnt--;
      if(vis[cnt]) return vis[cnt];
      memset(f,0,sizeof f);
      for(int i=1;i<=cnt;i++)
        cf(q[i].x,q[i].y);
        int ans=0,mx=0;
      for(int i=1;i<=n;i++) {
        ans+=f[i];
        if(ans==cnt) mx=max(mx,rnk[i]);
      }
      return vis[cnt]=mx;
    }
    int main() {
      scanf("%d%d",&n,&m);
      for(int i=1,a,b,c;i<n;i++) {
        scanf("%d%d%d",&a,&b,&c);
        add(a,b,c);add(b,a,c);
      }
      dfs1(1),dfs2(1,1);
      for(int i=1,a,b;i<=m;i++)
        scanf("%d%d",&q[i].x,&q[i].y),q[i].len=dis[q[i].x]+dis[q[i].y]-(dis[lca(q[i].x,q[i].y)]<<1);
      sort(q+1,q+1+m,cmp);
      int l=0,r=q[1].len;
      while(l<=r) {
        int mid=l+r>>1;
        if(q[1].len-check(mid)>mid) l=mid+1;
        else r=mid-1;
      }
      printf("%d",l);
    }
    
    我是咸鱼。转载博客请征得博主同意Orz
  • 相关阅读:
    [www.infoshare.cc]【抓包工具】wireshark
    【抓包工具】fiddler4
    apktool参数详解
    [www.infoshare.cc]jarsigner参数详解
    [www.infoshare.cc]【编译反编译工具使用】
    [www.infoshare.cc]【重签名工具】re-signer.jar使用
    adb常用操作命令
    【uiautomator】Ant实现快速调试
    [www.infoshare.cc]【uiautomator】报告简介及查看
    【uiautomator】UiSelector
  • 原文地址:https://www.cnblogs.com/sdfzhsz/p/9363498.html
Copyright © 2011-2022 走看看