• bzoj 2870 最长道路tree——边分治


    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2870

    关于边分治:https://www.cnblogs.com/Khada-Jhin/p/10154994.html

    自己写了那种把一个孩子连向自己,其他孩子连新建节点的重构图方法。

    如果 vector 里最后一个元素恰好是父亲的话,末尾就会有一个新建节点只有一个孩子。

    solve( ) 完之后要继续 get_rt( ) ,想知道两边的点数 ts ;可以发现 to[ cr ] 的部分点数恰好是 siz[ to[ cr ] ] ,另一部分就是 s - siz[ to[ cr ] ] 了。

    要递归的时候,如果 ts == 1 ,就不递归了。

    关于这道题:https://www.cnblogs.com/Miracevin/p/10430192.html

    虚点的点权就是它建出它的那个实点的点权;路径上的点数等于路径上的实边条数 + 1 。

    找出两边的路径,分别 sort 然后双指针即可。

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<vector>
    #define pb push_back
    #define ll long long
    using namespace std;
    int rdn()
    {
      int ret=0;bool fx=1;char ch=getchar();
      while(ch>'9'||ch<'0'){if(ch=='-')fx=0;ch=getchar();}
      while(ch>='0'&&ch<='9')ret=ret*10+ch-'0',ch=getchar();
      return fx?ret:-ret;
    }
    ll Mx(ll a,ll b){return a>b?a:b;}
    ll Mn(ll a,ll b){return a<b?a:b;}
    const int N=5e4+5,M=N<<1,INF=7e4;
    int n,vl[M],hd[M],xnt=1,to[M<<1],nxt[M<<1],w[M<<1];//xnt=1
    int siz[M],mn,Rt,tot[2]; bool vis[M]; ll ans;
    vector<int> vt[N];
    struct Node{
      int dis,mn;
      Node(int d=0,int m=0):dis(d),mn(m) {}
      bool operator< (const Node &b)const
      {return mn<b.mn;}
    }a[2][M];
    void add(int x,int  y,int z)
    {
      to[++xnt]=y;nxt[xnt]=hd[x];hd[x]=xnt;w[xnt]=z;
      to[++xnt]=x;nxt[xnt]=hd[y];hd[y]=xnt;w[xnt]=z;
    }
    void Rbuild(int cr,int fa)
    {
      for(int i=0,lm=vt[cr].size()-1,v,lst=0;i<=lm;i++)
        {
          if((v=vt[cr][i])==fa)continue;
          if(!lst) add(cr,v,1), lst=cr;
          else if(i==lm) add(lst,v,1);
          else 
        {
          n++; vl[n]=vl[cr];
          add(lst,n,0); add(n,v,1); lst=n;
        }
        }
      for(int i=0,lm=vt[cr].size(),v;i<lm;i++)
        if((v=vt[cr][i])!=fa)Rbuild(v,cr);
    }
    void get_rt(int cr,int fa,int s)
    {
      siz[cr]=1;
      for(int i=hd[cr],v,d;i;i=nxt[i])
        if(!vis[i>>1]&&(v=to[i])!=fa)
          {
        get_rt(v,cr,s); siz[cr]+=siz[v];
        d=Mx(siz[v],s-siz[v]);
        if(d<mn)mn=d, Rt=i;
          }
    }
    void dfs(int cr,int fa,int lj,int mn,bool fx)
    {
      mn=Mn(mn,vl[cr]); a[fx][++tot[fx]]=Node(lj,mn);
      for(int i=hd[cr],v;i;i=nxt[i])
        if(!vis[i>>1]&&(v=to[i])!=fa)
          dfs(v,cr,lj+w[i],mn,fx);
    }
    void cz()
    {
      for(int i=0;i<=1;i++)
        sort(a[i]+1,a[i]+tot[i]+1);
      int p0=tot[1]+1, lj=0, tw=w[Rt]+1;//+1
      for(int i=tot[0];i;i--)
        {
          int tmn=a[0][i].mn;
          while(p0>1&&a[1][p0-1].mn>=tmn)
        p0--, lj=Mx(lj,a[1][p0].dis);
          if(p0>tot[1])continue;//
          ans=Mx(ans,(ll)tmn*(lj+a[0][i].dis+tw));
        }
      p0=tot[0]+1; lj=0;
      for(int i=tot[1];i;i--)
        {
          int tmn=a[1][i].mn;
          while(p0>1&&a[0][p0-1].mn>=tmn)
        p0--, lj=Mx(lj,a[0][p0].dis);
          if(p0>tot[0])continue;//
          ans=Mx(ans,(ll)tmn*(lj+a[1][i].dis+tw));
        }
    }
    void solve(int cr,int s)
    {
      vis[cr>>1]=1;
      tot[0]=tot[1]=0;
      dfs(to[cr],0,0,INF,0); dfs(to[cr^1],0,0,INF,1);
      cz();
      int v=to[cr], ts=siz[v];
      if(ts>1){mn=N; get_rt(v,0,ts); solve(Rt,ts);}
      ts=s-ts; v=to[cr^1];// s-ts not s-siz[v] for siz[v] may changed!!!
      if(ts>1){mn=N; get_rt(v,0,ts); solve(Rt,ts);}
    }
    int main()
    {
      n=rdn();
      for(int i=1;i<=n;i++)vl[i]=rdn();
      for(int i=1,u,v;i<n;i++)
        {
          u=rdn();v=rdn(); vt[u].pb(v); vt[v].pb(u);
        }
      Rbuild(1,0);
      mn=N;get_rt(1,0,n);solve(Rt,n);
      printf("%lld
    ",ans);
      return 0;
    }
  • 相关阅读:
    Django----路由控制
    Django-ORM的使用
    Django-ORM框架
    Django对数据库表的操作
    Python操作mysql
    [mysql]linux mysql 基础命令操作
    [mysql]linux mysql 读写分离
    [mysql]linux mysql 主从复制
    [mysql 1]linux mysal 安装
    [mysql]linux mysal 安装
  • 原文地址:https://www.cnblogs.com/Narh/p/10457963.html
Copyright © 2020-2023  润新知