• [bzoj3784]树上的路径


    点分治,当一个节点作为重心时,统计出:1.每一个点的深度;2.每一个点所能选择的路径对应点区间,可以发现这样的点数只需要nlogn。然后类似于bzoj2006超级钢琴的堆+线段树来做即可。

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 #define N 50005
      4 #define L (k<<1)
      5 #define R (L+1)
      6 #define mid (l+r>>1)
      7 struct ji{
      8     int nex,to,len;
      9 }edge[N<<1];
     10 int E,r,n,m,x,y,z,tot,s[N*20],sz[N],head[N],vis[N],f[N*80];
     11 struct ji2{
     12     int l,r;
     13 }a[N*20];
     14 struct ji3{
     15     int k,l,r,mx;
     16     bool operator < (const ji3 &t)const{
     17         return s[k]+s[mx]<s[t.k]+s[t.mx];
     18     }
     19 };
     20 priority_queue<ji3>q;
     21 int up(int x,int y){
     22     if (s[x]>s[y])return x;
     23     return y;
     24 }
     25 void update(int k,int l,int r,int x){
     26     if (l==r){
     27         f[k]=l;
     28         return;
     29     }
     30     if (x<=mid)update(L,l,mid,x);
     31     else update(R,mid+1,r,x);
     32     f[k]=up(f[L],f[R]);
     33 }
     34 int query(int k,int l,int r,int x,int y){
     35     if ((l>y)||(x>r))return 0;
     36     if ((x<=l)&&(r<=y))return f[k];
     37     return up(query(L,l,mid,x,y),query(R,mid+1,r,x,y));
     38 }
     39 void add(int k,int x,int y){
     40     q.push(ji3{k,x,y,query(1,1,tot,x,y)});
     41 }
     42 void add_edge(int x,int y,int z){
     43     edge[E].nex=head[x];
     44     edge[E].to=y;
     45     edge[E].len=z;
     46     head[x]=E++;
     47 }
     48 void size(int k,int fa){
     49     sz[k]=1;
     50     for(int i=head[k];i!=-1;i=edge[i].nex)
     51         if ((!vis[edge[i].to])&&(edge[i].to!=fa)){
     52             size(edge[i].to,k);
     53             sz[k]+=sz[edge[i].to];
     54         }
     55 }
     56 void find(int k,int fa,int s){
     57     int t=s-sz[k];
     58     for(int i=head[k];i!=-1;i=edge[i].nex)
     59         if ((!vis[edge[i].to])&&(edge[i].to!=fa)){
     60             find(edge[i].to,k,s);
     61             t=max(t,sz[edge[i].to]);
     62         }
     63     if (t<=s/2)r=k;
     64 }
     65 void calc(int k,int fa,int sh){
     66     if (fa)a[++tot]=ji2{x,y};
     67     else a[x=y=++tot]=ji2{0,0};
     68     s[tot]=sh;
     69     for(int i=head[k];i!=-1;i=edge[i].nex)
     70         if ((!vis[edge[i].to])&&(edge[i].to!=fa)){
     71             calc(edge[i].to,k,sh+edge[i].len);
     72             if (!fa)y=tot;
     73         }
     74 }
     75 void dfs(int k){
     76     size(k,0);
     77     find(k,0,sz[k]);
     78     calc(k=r,0,0);
     79     vis[k]=1;
     80     for(int i=head[k];i!=-1;i=edge[i].nex)
     81         if (!vis[edge[i].to])dfs(edge[i].to);
     82 }
     83 int main(){
     84     scanf("%d%d",&n,&m);
     85     memset(head,-1,sizeof(head));
     86     for(int i=1;i<n;i++){
     87         scanf("%d%d%d",&x,&y,&z);
     88         add_edge(x,y,z);
     89         add_edge(y,x,z);
     90     }
     91     dfs(1);
     92     s[0]=-0x3f3f3f3f;
     93     for(int i=1;i<=tot;i++)update(1,1,tot,i);
     94     for(int i=1;i<=tot;i++)add(i,a[i].l,a[i].r);
     95     for(int i=1;i<=m;i++){
     96         ji3 o=q.top();
     97         q.pop();
     98         printf("%d\n",s[o.k]+s[o.mx]);
     99         if (o.l<o.mx)add(o.k,o.l,o.mx-1);
    100         if (o.mx<o.r)add(o.k,o.mx+1,o.r);
    101     }
    102 }
    View Code
  • 相关阅读:
    python之基础2
    python之文件2
    python之入门2
    python之入门
    python之多并发2
    python之面向对象2
    python之MySQL系列
    python之文件
    python之多并发
    Google身份验证器详解
  • 原文地址:https://www.cnblogs.com/PYWBKTDA/p/11337669.html
Copyright © 2020-2023  润新知