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\n",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\n",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\n",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 }

 

posted @ 2017-03-27 21:15  SilverNebula  阅读(139)  评论(0编辑  收藏  举报
AmazingCounters.com