bzoj 3611

和BZOJ消耗站一样,先将那个询问的简图构建出来,然后就是简单的树形DP。

(倍增数组开小了,然后就狂WA,自己生成的极限数据深度又没有那么高,链又奇迹般正确)

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <vector>
  4 #include <algorithm>
  5 #define min(a,b) ((a)<(b)?(a):(b))
  6 #define max(a,b) ((a)>(b)?(a):(b))
  7 #define oo 0x3f3f3f3f3f3f3f3f
  8 #define N 1000010
  9 #define P 19
 10 using namespace std;
 11
 12 typedef long long dnt;
 13
 14 int n, m;
 15 vector<int> g[N];
 16 int dfn[N], anc[N][P+1], dep[N], idc;
 17 int head[N], ikey[N], dest[N+N], next[N+N], etot;
 18 dnt dp[N][4];
 19 int qcnt, aa[N], stk[N], top;
 20 dnt ans[3];
 21
 22 void adde( int u, int v ) {
 23     etot++;
 24     next[etot] = head[u];
 25     dest[etot] = v;
 26     head[u] = etot;
 27 }
 28 void dfs( int u ) {
 29     dfn[u] = ++idc;
 30     for( int p=1; p<=P; p++ )
 31         anc[u][p] = anc[anc[u][p-1]][p-1];
 32     for( int t=0; t<g[u].size(); t++ ) {
 33         int v=g[u][t];
 34         if( v==anc[u][0] ) continue;
 35         anc[v][0] = u;
 36         dep[v] = dep[u]+1;
 37         dfs(v);
 38     }
 39 }
 40 bool cmp( int u, int v ) {
 41     return dfn[u]<dfn[v];
 42 }
 43 int lca( int u, int v ) {
 44     if( dep[u]<dep[v] ) swap(u,v);
 45     int t=dep[u]-dep[v];
 46     for( int p=0; t; t>>=1,p++ )
 47         if( t&1 ) u=anc[u][p];
 48     if( u==v ) return u;
 49     for( int p=P; p>=0 && anc[u][0]!=anc[v][0]; p-- )
 50         if( anc[u][p]!=anc[v][p] ) u=anc[u][p], v=anc[v][p];
 51     return anc[u][0];
 52 }
 53 void build() {
 54     stk[top=1] = 1;
 55     head[1] = 0;
 56
 57     sort( aa+1, aa+1+qcnt, cmp );
 58
 59     etot = 0;
 60     for( int i=2-(aa[1]!=1); i<=qcnt; i++ ) {
 61         int ca=lca(aa[i],stk[top]);
 62         while( dep[ca]<dep[stk[top]] ) {
 63             int u;
 64             u = stk[top--];
 65             if( dep[ca]>=dep[stk[top]] ) {
 66                 if( ca!=stk[top] ) {
 67                     stk[++top] = ca;
 68                     head[ca] = 0;
 69                 }
 70                 adde( stk[top], u );
 71                 break;
 72             }
 73             adde( stk[top], u );
 74         }
 75         stk[++top] = aa[i];
 76         head[aa[i]] = 0;
 77     }
 78     for( int i=top; i>=2; i-- )
 79         adde( stk[i-1], stk[i] );
 80 }
 81 dnt sml, big, sum, cnt;
 82 void dodp( int u ) {
 83     if( ikey[u] ) {
 84         dp[u][0] = 0;
 85         dp[u][1] = 0;
 86         dp[u][2] = 1;
 87         dp[u][3] = 0;
 88     } else {
 89         dp[u][0] = oo;
 90         dp[u][1] = -oo;
 91         dp[u][2] = 0;
 92         dp[u][3] = 0;
 93     }
 94     for( int t=head[u]; t; t=next[t] ) {
 95         int v=dest[t];
 96         dnt w=dep[v]-dep[u];
 97         dodp(v);
 98         dp[u][0] = min( dp[u][0], dp[v][0]+w );
 99         dp[u][1] = max( dp[u][1], dp[v][1]+w );
100         dp[u][2] += dp[v][2];
101         dp[u][3] += dp[v][3]+w*dp[v][2];
102     }
103     if( ikey[u] ) {
104         sml = 0;
105         big = 0;
106         sum = 0;
107         cnt = 1;
108     } else {
109         sml = oo;
110         big = -oo;
111         sum = 0;
112         cnt = 0;
113     }
114     for( int t=head[u]; t; t=next[t] ) {
115         int v=dest[t];
116         dnt w=dep[v]-dep[u];
117         ans[0] = min( ans[0], sml+w+dp[v][0] );
118         ans[1] = max( ans[1], big+w+dp[v][1] );
119         ans[2] += cnt*(dp[v][3]+w*dp[v][2]) + sum*dp[v][2];
120         sml = min( sml, dp[v][0]+w );
121         big = max( big, dp[v][1]+w );
122         cnt += dp[v][2];
123         sum += dp[v][3]+w*dp[v][2];
124     }
125 }
126 int main() {
127     scanf( "%d", &n );
128     for( int i=1,u,v; i<n; i++ ) {
129         scanf( "%d%d", &u, &v );
130         g[u].push_back( v );
131         g[v].push_back( u );
132     }
133     anc[1][0] = 1;
134     dep[1] = 0;
135     dfs(1);
136     scanf( "%d", &m );
137     for( int i=1; i<=m; i++ ) {
138         scanf( "%d", &qcnt );
139         for( int j=1; j<=qcnt; j++ )
140             scanf( "%d", aa+j );
141
142         if( qcnt==1 ) {
143             printf( "0 0 0\n" );
144             continue;
145         }
146
147         build();
148
149         for( int j=1; j<=qcnt; j++ )
150             ikey[aa[j]] = 1;
151         ans[0] = oo;
152         ans[1] = 0;
153         ans[2] = 0;
154         dodp(1);
155         for( int j=1; j<=qcnt; j++ )
156             ikey[aa[j]] = 0;
157
158         printf( "%lld %lld %lld\n", ans[2], ans[0], ans[1] );
159     }
160 }

时间: 2025-01-03 18:38:44

bzoj 3611的相关文章

bzoj 3611: [Heoi2014]大工程

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

大工程(bzoj 3611)

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

BZOJ 3611: [Heoi2014]大工程 [虚树 DP]

传送门 题意: 多次询问,求最长链最短链链总长 煞笔$DP$记录$d,c,f,g$ $MD$该死拍了一下午没问题然后交上去就$T$ 然后发现树链剖分写成$size[v]+=size[u]$ 我想知道我随机生成的大数据是怎么跑过去的!!!!!!!! #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> using

BZOJ 3611 HEOI2014 大工程 倍增LCA+单调栈+树形DP

题目大意:给定一棵树,m次询问,每次给出k个关键点,询问这k个点之间的两两距离和.最小距离和最大距离 n<=100W,m<=50000,Σk<=2*n 处理方法同2286 消耗战 地址见 http://blog.csdn.net/popoqqq/article/details/42493725 这个题的DP有些麻烦 因此我把要处理的节点单独拎出来做的DP 具体状态和转移见代码 #include <cstdio> #include <cstring> #includ

BZOJ 3611 HEOI 2014 大工程 LCA单调性

题目大意:给出一棵树,每次询问一些节点,当把这些节点连接起来,使得每两个询问的点之间有一条边,共有k*(k - 1)条边.问这些边中,长度的总和是多少,最短的一条边是多少,最长的一条边是多少.保证询问的点的总数是O(n)级别. 思路:利用LCA单调性,每次询问的时候重新建树,在这棵树上做DP,使得总体时间复杂度降到O(nlogn). 树形DP我写的都要麻烦死了..听了正解之后简直想吐血.. 我的做法是维护四个数组,sum,size,_min,_max,分别表示以当前节点为根节点的子树中的所有关键

【BZOJ】【3611】【HEOI2014】大工程

虚树+树形DP 本题100W的点数……不用虚树真的好吗…… Orz ZYF 我的感悟: dp的过程跟SPOJ 1825 FTOUR2 的做法类似,依次枚举每个子树,从当前子树和之前的部分中各找一条最长(短)路径更新答案,再把这个子树的最短路径加入到x节点中去(之前算过的部分)这样就实现了枚举所有可能的最优情况!而且复杂度很低!避免了两两之间的枚举…… 1 /************************************************************** 2 Probl

BZOJ 1013: [JSOI2008]球形空间产生器sphere

二次联通门 : BZOJ 1013: [JSOI2008]球形空间产生器sphere /* BZOJ 1013: [JSOI2008]球形空间产生器sphere 高斯消元 QAQ SB的我也能终于能秒题了啊 设球心的坐标为(x,y,z...) 那么就可以列n+1个方程,化化式子高斯消元即可 */ #include <cstdio> #include <iostream> #include <cstring> #define rg register #define Max

bzoj 3309 DZY Loves Math - 莫比乌斯反演 - 线性筛

对于正整数n,定义f(n)为n所含质因子的最大幂指数.例如f(1960)=f(2^3 * 5^1 * 7^2)=3, f(10007)=1, f(1)=0. 给定正整数a,b,求sigma(sigma(f(gcd(i,j)))) (i=1..a, j=1..b). Input 第一行一个数T,表示询问数. 接下来T行,每行两个数a,b,表示一个询问. Output 对于每一个询问,输出一行一个非负整数作为回答. Sample Input 4 7558588 9653114 6514903 445

【BZOJ】[HNOI2009]有趣的数列

[算法]Catalan数 [题解] 学了卡特兰数就会啦>_<! 因为奇偶各自递增,所以确定了奇偶各自的数字后排列唯一. 那么就是给2n个数分奇偶了,是不是有点像入栈出栈序呢. 将做偶数标为-1,做奇数标为+1,显然当偶数多于奇数时不合法,因为它压不住后面的奇数. 然后其实这种题目,打表就可知啦--QAQ 然后问题就是求1/(n+1)*C(2n,n)%p了,p不一定是素数. 参考bzoj礼物的解法. 看到网上清一色的素数筛+分解质因数解法,不解了好久,感觉写了假的礼物-- 后来觉得礼物的做法才比