[bzoj3611][Heoi2014]大工程

  看题目感觉应该就是传说中的虚树?

  然后跑去学了一发。。。自己YY了一下然后挂飞。。于是就只好抄模板了T_T

  建完虚树就是个树形dp。。。

  对于询问总和:每条边对答案的贡献是边权*一端的节点数*另一端的节点数。(这里的节点不包括建虚树时添上去的点)

  对于询问最小值最大值,每次计算出经过这个节点的最长||最短路径长度就好了。。

  大概这种题条件都有一个sigma(K)<=n之类的。。而且题目求的东西得符合区间加法。。。不然你把边合在一起也没用>_<

  链剖求lca果然快。。。速度能进前10.。。然而代码长度实在感人= =

  1 #include<cstdio>
  2 #include<iostream>
  3 #include<cstring>
  4 #include<algorithm>
  5 #define ll long long
  6 using namespace std;
  7 const int maxn=1000023;
  8 const int inf=1002333333;
  9 struct zs{
 10     int too,pre;
 11 }e[maxn<<1];
 12 struct zs1{
 13     int too,pre,dis;
 14 }e1[maxn<<2];
 15 int tot,tot1,last[maxn],last1[maxn];
 16 int sz[maxn],mn[maxn],mx[maxn];
 17 int intree[maxn],poi[maxn],rt;
 18 int dfn[maxn],bel[maxn],size[maxn],dep[maxn],fa[maxn],tim;
 19 int st[maxn],top;
 20 int ansmn,ansmx;
 21 ll anssum;
 22 int i,j,k,n,m,K,a,b,lca;
 23  
 24  
 25 int ra;char rx;
 26 inline int read(){
 27     rx=getchar(),ra=0;
 28     while(rx<'0'||rx>'9')rx=getchar();
 29     while(rx>='0'&&rx<='9')ra*=10,ra+=rx-48,rx=getchar();return ra;
 30 }
 31  
 32  
 33 inline void insert(int a,int b){
 34     e[++tot].too=b,e[tot].pre=last[a],last[a]=tot;
 35     e[++tot].too=a,e[tot].pre=last[b],last[b]=tot;
 36 }
 37 inline void ins(int a,int b){
 38 //  printf("   %d-->%d\n",a,b);
 39     e1[++tot1].too=b,e1[tot1].dis=dep[b]-dep[a],e1[tot1].pre=last1[a],last1[a]=tot1;
 40 }
 41  
 42  
 43 void dfs1(int x){
 44     size[x]=1;
 45     for(int i=last[x];i;i=e[i].pre)
 46         if(e[i].too!=fa[x])
 47             fa[e[i].too]=x,
 48             dfs1(e[i].too),
 49             size[x]+=size[e[i].too];
 50 }
 51 void dfs2(int x,int chain){
 52     bel[x]=chain,dfn[x]=++tim,dep[x]=dep[fa[x]]+1;int mxpos=0,i,to;
 53     for(to=e[i=last[x]].too;i;to=e[i=e[i].pre].too)
 54         if(to!=fa[x]&&size[to]>size[mxpos])mxpos=to;
 55     if(!mxpos)return;
 56     dfs2(mxpos,chain);
 57     for(to=e[i=last[x]].too;i;to=e[i=e[i].pre].too)
 58         if(to!=fa[x]&&to!=mxpos)dfs2(to,to);
 59 }
 60 inline int getlca(int a,int b){
 61     if(dep[bel[a]]<dep[bel[b]])swap(a,b);
 62     while(bel[a]!=bel[b]){
 63         a=fa[bel[a]];
 64         if(dep[bel[a]]<dep[bel[b]])swap(a,b);
 65     }
 66     return dep[a]<dep[b]?a:b;
 67 }
 68  
 69  
 70 bool cmp(int a,int b){return dfn[a]<dfn[b];}
 71  
 72 inline int min(int a,int b){return a<b?a:b;}
 73 inline int max(int a,int b){return a>b?a:b;}
 74 void dp(int x){
 75     register int i,to;
 76     if(intree[x]==m)sz[x]=1,mn[x]=mx[x]=0;
 77         else sz[x]=0,mn[x]=inf,mx[x]=-inf;
 78     for(to=e1[i=last1[x]].too;i;to=e1[i=e1[i].pre].too){
 79         dp(to),sz[x]+=sz[to],mn[to]+=e1[i].dis,mx[to]+=e1[i].dis;
 80         anssum+=(ll)sz[to]*(K-sz[to])*e1[i].dis;
 81         if(mn[x]+mn[to]<ansmn)ansmn=mn[x]+mn[to];
 82         if(mx[to]+mx[x]>ansmx)ansmx=mx[x]+mx[to];
 83         if(mn[to]<mn[x])mn[x]=mn[to];if(mx[to]>mx[x])mx[x]=mx[to];
 84     }
 85     last1[x]=0;
 86 }
 87  
 88  
 89 char s[23];int len;
 90 inline void outll(ll x){
 91     if(!x){putchar('0');return;}
 92     for(len=0;x;s[++len]=x%10,x/=10);
 93     while(len)putchar(s[len--]+48);
 94 }
 95 inline void outint(int x){
 96     if(!x){putchar('0');return;}
 97     for(len=0;x;s[++len]=x%10,x/=10);
 98     while(len)putchar(s[len--]+48);
 99 }
100  
101  
102 int main(){
103     register int i;
104     n=read();
105     for(i=1;i<n;i++)a=read(),b=read(),insert(a,b);
106     dfs1(1),dfs2(1,1);
107 //  for(i=1;i<=n;i++)printf("  %d  %d\n",dep[i],dfn[i]);
108 //  for(i=1;i<n;i++)for(j=i+1;j<=n;j++)printf("  %d&&%d %d\n",i,j,getlca(i,j));
109     for(m=read();m;m--){
110         tot1=0;
111         for(K=read(),i=1;i<=K;i++)intree[poi[i]=read()]=m;
112         sort(poi+1,poi+1+K,cmp);top=1,st[1]=poi[1];
113 //      for(i=1;i<=K;i++)printf("  %d\n",poi[i]);
114         for(i=2;i<=K;i++){
115             lca=getlca(poi[i],st[top]);
116             while(dfn[lca]<dfn[st[top]]&&top)
117                 if(dfn[st[top-1]]<=dfn[lca]){
118                     ins(lca,st[top--]);
119                     if(st[top]!=lca)st[++top]=lca;
120                 }else ins(st[top-1],st[top]),top--;
121             st[++top]=poi[i];
122         }
123         while(top>1)ins(st[top-1],st[top]),top--;
124         ansmn=inf,ansmx=anssum=0,rt=st[1],
125         dp(rt);
126         outll(anssum),putchar(' '),outint(ansmn),putchar(' '),outint(ansmx),putchar('\n');
127     }
128     return 0;
129 }
View Code

 

posted @ 2016-02-12 20:06  czllgzmzl  阅读(166)  评论(0编辑  收藏  举报