• Bzoj3611 [Heoi2014]大工程


    Time Limit: 60 Sec  Memory Limit: 512 MB
    Submit: 1281  Solved: 557

    Description

    国家有一个大工程,要给一个非常大的交通网络里建一些新的通道。 
    我们这个国家位置非常特殊,可以看成是一个单位边权的树,城市位于顶点上。 
    在 2 个国家 a,b 之间建一条新通道需要的代价为树上 a,b 的最短路径。
     现在国家有很多个计划,每个计划都是这样,我们选中了 k 个点,然后在它们两两之间 新建 C(k,2)条 新通道。
    现在对于每个计划,我们想知道:
     1.这些新通道的代价和
     2.这些新通道中代价最小的是多少 
    3.这些新通道中代价最大的是多少
     

    Input

    第一行 n 表示点数。

     接下来 n-1 行,每行两个数 a,b 表示 a 和 b 之间有一条边。
    点从 1 开始标号。 接下来一行 q 表示计划数。
    对每个计划有 2 行,第一行 k 表示这个计划选中了几个点。
     第二行用空格隔开的 k 个互不相同的数表示选了哪 k 个点。
     

    Output

    输出 q 行,每行三个数分别表示代价和,最小代价,最大代价。 

     

    Sample Input

    10
    2 1
    3 2
    4 1
    5 2
    6 4
    7 5
    8 6
    9 7
    10 9
    5
    2
    5 4
    2
    10 4
    2
    5 2
    2
    6 1
    2
    6 1

    Sample Output

    3 3 3
    6 6 6
    1 1 1
    2 2 2
    2 2 2

    HINT

    n<=1000000 


    q<=50000并且保证所有k之和<=2*n 

    Source

    树 虚树 树形DP

    这次由于要统计每个点之间的信息,所以不能像2286那样偷懒少连子树的关键点了。

    把每个关键点建到虚树上,然后跑树规

    转移方程见代码。

    自己写的方程各种乱还WAWAWA,于是拜读了黄学长的题解。(读书人的事……)

    AC以后一看时间,10000+ms。

    咋回事儿啊这么慢(懵X脸)

      1 /*by SilverN*/
      2 #include<algorithm>
      3 #include<iostream>
      4 #include<cstring>
      5 #include<cstdio>
      6 #include<cmath>
      7 #include<vector>
      8 #define LL long long
      9 using namespace std;
     10 const int INF=0x3f3f3f3f;
     11 const int mxn=1000010;
     12 int read(){
     13     int x=0,f=1;char ch=getchar();
     14     while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();}
     15     while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();}
     16     return x*f;
     17 }
     18 struct edge{
     19     int v,nxt,w;
     20 }e[mxn<<1],eg[mxn<<1];
     21 int hd[mxn],hd2[mxn],mct=0;
     22 void add_edge(int u,int v){
     23     e[++mct].v=v;e[mct].nxt=hd[u];hd[u]=mct;return;
     24 }
     25 int dep[mxn];
     26 void add(int u,int v){
     27     if(u==v)return;
     28     eg[++mct].v=v;eg[mct].w=dep[v]-dep[u];eg[mct].nxt=hd2[u];hd2[u]=mct;
     29     return;
     30 }
     31 //int dis[mxn];
     32 int fa[mxn][21];
     33 int ind[mxn],out[mxn],dtime=0;
     34 void DFS(int u,int ff){
     35     dep[u]=dep[ff]+1;
     36     ind[u]=++dtime;
     37     for(int i=1;i<=20;i++)fa[u][i]=fa[fa[u][i-1]][i-1];
     38     for(int i=hd[u],v;i;i=e[i].nxt){
     39         if(e[i].v==ff)continue;
     40         v=e[i].v;
     41         fa[v][0]=u;
     42 //        dis[v]=dis[u]+1;
     43         DFS(v,u);
     44     }
     45     out[u]=dtime;
     46     return;
     47 }
     48 int LCA(int x,int y){
     49     if(dep[x]<dep[y])swap(x,y);
     50     for(int i=20;i>=0;i--)
     51         if(dep[fa[x][i]]>=dep[y])x=fa[x][i];
     52     if(x==y)return y;
     53     for(int i=20;i>=0;i--){
     54         if(fa[x][i]!=fa[y][i])x=fa[x][i],y=fa[y][i];
     55     }
     56     return fa[x][0];
     57 }
     58 int fmi[mxn],fmx[mxn],sz[mxn];
     59 LL f[mxn],smm;
     60 int ansmin,ansmax;
     61 bool inq[mxn];
     62 void DP(int u){
     63     sz[u]=inq[u];
     64     f[u]=0;
     65     fmi[u]=inq[u]?0:INF;
     66     fmx[u]=inq[u]?0:-INF;
     67 //    printf("u:%d %d %d
    ",u,fmi[u],fmx[u]);
     68     for(int i=hd2[u],v;i;i=eg[i].nxt){
     69         v=eg[i].v;
     70         DP(v);
     71         smm+=(f[u]+sz[u]*eg[i].w)*(LL)sz[v]+f[v]*sz[u];//
     72         sz[u]+=sz[v];
     73         f[u]+=f[v]+eg[i].w*sz[v];
     74         ansmin=min(ansmin,fmi[u]+fmi[v]+eg[i].w);
     75         ansmax=max(ansmax,fmx[u]+fmx[v]+eg[i].w);
     76         fmi[u]=min(fmi[v]+eg[i].w,fmi[u]);
     77         fmx[u]=max(fmx[v]+eg[i].w,fmx[u]);
     78     }
     79     hd2[u]=0;
     80     return;
     81 }
     82 int a[mxn],st[mxn],top=0;
     83 int cmp(int a,int b){return ind[a]<ind[b];}
     84 void solve(){
     85     mct=0;
     86     int i,j,K=read();
     87     for(i=1;i<=K;i++){a[i]=read();}
     88     sort(a+1,a+K+1,cmp);
     89     st[top=1]=1;
     90     for(i=1;i<=K;i++)inq[a[i]]=1;
     91     for(i=1;i<=K;i++){
     92         int now=a[i],tmp=LCA(a[i],st[top]);
     93         if(tmp==st[top]){st[++top]=a[i];continue;}
     94         while(1){
     95             if(dep[tmp]>=dep[st[top-1]]){
     96                 add(tmp,st[top--]);
     97                 if(st[top]!=tmp)st[++top]=tmp;
     98                 break;
     99             }
    100             add(st[top-1],st[top]);top--;
    101         }
    102         if(st[top]!=now)st[++top]=now;
    103     }
    104     while(--top)add(st[top],st[top+1]);
    105     smm=0;ansmin=INF;ansmax=-INF;
    106     DP(1);
    107     for(i=1;i<=K;i++)inq[a[i]]=0;
    108     printf("%lld %d %d
    ",smm,ansmin,ansmax);
    109     return;
    110 }
    111 int n,q;
    112 int main(){
    113     int i,j,u,v;
    114     n=read();
    115     for(i=1;i<n;i++){
    116         u=read();v=read();
    117         add_edge(u,v);
    118         add_edge(v,u);
    119     }
    120     DFS(1,0);
    121     q=read();
    122     while(q--)solve();
    123     return 0;
    124 }
    倍增LCA

    看到有人写树剖,那我也来个树剖LCA吧

    于是跑到了3808ms,挤到了status第二页。

    树剖真神奇

      1 /*by SilverN*/
      2 #include<algorithm>
      3 #include<iostream>
      4 #include<cstring>
      5 #include<cstdio>
      6 #include<cmath>
      7 #include<vector>
      8 #define LL long long
      9 using namespace std;
     10 const int INF=0x3f3f3f3f;
     11 const int mxn=1000010;
     12 int read(){
     13     int x=0,f=1;char ch=getchar();
     14     while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();}
     15     while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();}
     16     return x*f;
     17 }
     18 struct edge{
     19     int v,nxt,w;
     20 }e[mxn<<1],eg[mxn<<1];
     21 int hd[mxn],hd2[mxn],mct=0;
     22 void add_edge(int u,int v){
     23     e[++mct].v=v;e[mct].nxt=hd[u];hd[u]=mct;return;
     24 }
     25 int dep[mxn];
     26 void add(int u,int v){
     27     if(u==v)return;
     28     eg[++mct].v=v;eg[mct].w=dep[v]-dep[u];eg[mct].nxt=hd2[u];hd2[u]=mct;
     29     return;
     30 }
     31 //
     32 int ind[mxn],out[mxn],dtime=0;
     33 struct node{
     34     int fa,top,son;
     35     int sz;
     36 }t[mxn];
     37 void DFS(int u,int ff){
     38     dep[u]=dep[ff]+1;
     39     t[u].sz++;
     40     for(int i=hd[u],v;i;i=e[i].nxt){
     41         if(e[i].v==ff)continue;
     42         v=e[i].v;
     43         t[v].fa=u;
     44         DFS(v,u);
     45         t[u].sz+=t[v].sz;
     46         if(t[v].sz>t[t[u].son].sz)
     47             t[u].son=v;
     48     }
     49 
     50     return;
     51 }
     52 void DFS2(int u,int top){
     53     ind[u]=++dtime;
     54     t[u].top=top;
     55     if(t[u].son){
     56         DFS2(t[u].son,top);
     57         for(int i=hd[u];i;i=e[i].nxt){
     58             if(e[i].v==t[u].son || e[i].v==t[u].fa)continue;
     59             DFS2(e[i].v,e[i].v);
     60         }
     61     }
     62     out[u]=dtime;
     63     return;
     64 }
     65 int LCA(int x,int y){
     66     while(t[x].top!=t[y].top){
     67         if(dep[t[x].top]<dep[t[y].top])swap(x,y);
     68         x=t[t[x].top].fa;
     69     }
     70     return dep[x]<dep[y]?x:y;
     71 }
     72 //
     73 int fmi[mxn],fmx[mxn],sz[mxn];
     74 LL f[mxn],smm;
     75 int ansmin,ansmax;
     76 bool inq[mxn];//标记关键点 
     77 void DP(int u){
     78     sz[u]=inq[u];
     79     f[u]=0;
     80     fmi[u]=inq[u]?0:INF;
     81     fmx[u]=inq[u]?0:-INF;
     82     for(int i=hd2[u],v;i;i=eg[i].nxt){
     83         v=eg[i].v;
     84         DP(v);
     85         smm+=(f[u]+sz[u]*eg[i].w)*(LL)sz[v]+f[v]*sz[u];//
     86         sz[u]+=sz[v];
     87         f[u]+=f[v]+eg[i].w*sz[v];
     88         ansmin=min(ansmin,fmi[u]+fmi[v]+eg[i].w);
     89         ansmax=max(ansmax,fmx[u]+fmx[v]+eg[i].w);
     90         fmi[u]=min(fmi[v]+eg[i].w,fmi[u]);
     91         fmx[u]=max(fmx[v]+eg[i].w,fmx[u]);
     92     }
     93     hd2[u]=0;
     94     return;
     95 }
     96 int a[mxn],st[mxn],top=0;
     97 int cmp(int a,int b){return ind[a]<ind[b];}
     98 void solve(){
     99     mct=0;
    100     int i,j,K=read();
    101     for(i=1;i<=K;i++){a[i]=read();}
    102     sort(a+1,a+K+1,cmp);
    103     st[top=1]=1;
    104     for(i=1;i<=K;i++)inq[a[i]]=1;
    105     for(i=1;i<=K;i++){
    106         int now=a[i],tmp=LCA(a[i],st[top]);
    107         if(tmp==st[top]){st[++top]=a[i];continue;}
    108         while(1){
    109             if(dep[tmp]>=dep[st[top-1]]){
    110                 add(tmp,st[top--]);
    111                 if(st[top]!=tmp)st[++top]=tmp;
    112                 break;
    113             }
    114             add(st[top-1],st[top]);top--;
    115         }
    116         if(st[top]!=now)st[++top]=now;
    117     }
    118     while(--top)add(st[top],st[top+1]);
    119     smm=0;ansmin=INF;ansmax=-INF;
    120     DP(1);
    121     for(i=1;i<=K;i++)inq[a[i]]=0;
    122     printf("%lld %d %d
    ",smm,ansmin,ansmax);
    123     return;
    124 }
    125 int n,q;
    126 int main(){
    127     int i,j,u,v;
    128     n=read();
    129     for(i=1;i<n;i++){
    130         u=read();v=read();
    131         add_edge(u,v);
    132         add_edge(v,u);
    133     }
    134     DFS(1,0);
    135     DFS2(1,1);
    136     q=read();
    137     while(q--)solve();
    138     return 0;
    139 }
  • 相关阅读:
    pat 1029. Median (25)
    pat 1040. Longest Symmetric String (25)
    pat 1037. Magic Coupon (25)
    pat 1058. A+B in Hogwarts (20)
    pat 1083. List Grades (25)
    pat 1054. The Dominant Color (20)
    pat 1042. Shuffling Machine (20)
    pat 1061. Dating (20)
    *分支-11. 计算工资
    分支-10. 计算个人所得税
  • 原文地址:https://www.cnblogs.com/SilverNebula/p/6628840.html
Copyright © 2020-2023  润新知