题意:一棵树上有m个红色结点,树的边有权值。q次查询,每次给出k个点,每次查询有且只有一次机会将n个点中任意一个点染红,令k个点中距离红色祖先距离最大的那个点的距离最小化。q次查询相互独立。

分析:数据量很... 最大值最小化,二分搜答案。将ST表求lca的dfs函数加一点东西,求出每个点到其最近红色祖先的距离。check函数中,枚举到其红色祖先的距离超过下限的点。设非法点数为p,尝试将其距离通过一次染色缩小。具体做法是求出这p个点的lca,这个点就是要染红的点,因为只有修改这个点,才有可能将所有点的红祖先距离都缩减。若修改之后仍有结点非法,则check失败

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. typedef long long LL;
  4. const int N=100005;
  5. struct node{
  6. int v,next;
  7. LL dis;
  8. }edges[N<<1];
  9. int head[N],e;
  10. int id[N]; //节点第一次被遍历的顺序
  11. LL dis[N]; //节点到根节点的距离
  12. LL rdis[N]; //距离最近的红色祖先的距离
  13. bool red[N];
  14. int RMQ[N*2][20];
  15. int curID;
  16. //F[i]表示第i个遍历的节点
  17. //B[i]表示F[i]在树中的深度
  18. int F[N*2],B[N*2];
  19. int n,m,Q,root;
  20. #include<bits/stdc++.h>
  21. using namespace std;
  22. ////////////////
  23. namespace IO {
  24. #define BUF_SIZE 100000
  25. #define OUT_SIZE 100000
  26. #define ll long long
  27. //fread->read
  28. bool IOerror = 0;
  29. inline char nc() {
  30. static char buf[BUF_SIZE], *p1 = buf + BUF_SIZE, *pend = buf + BUF_SIZE;
  31. if (p1 == pend) {
  32. p1 = buf; pend = buf + fread(buf, 1, BUF_SIZE, stdin);
  33. if (pend == p1) { IOerror = 1; return -1; }
  34. //{printf("IO error!\n");system("pause");for (;;);exit(0);}
  35. }
  36. return *p1++;
  37. }
  38. inline bool blank(char ch) { return ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t'; }
  39. inline void read(int &x) {
  40. bool sign = 0; char ch = nc(); x = 0;
  41. for (; blank(ch); ch = nc());
  42. if (IOerror)return;
  43. if (ch == '-')sign = 1, ch = nc();
  44. for (; ch >= '0'&&ch <= '9'; ch = nc())x = x * 10 + ch - '0';
  45. if (sign)x = -x;
  46. }
  47. inline void read(ll &x) {
  48. bool sign = 0; char ch = nc(); x = 0;
  49. for (; blank(ch); ch = nc());
  50. if (IOerror)return;
  51. if (ch == '-')sign = 1, ch = nc();
  52. for (; ch >= '0'&&ch <= '9'; ch = nc())x = x * 10 + ch - '0';
  53. if (sign)x = -x;
  54. }
  55. inline void read(double &x) {
  56. bool sign = 0; char ch = nc(); x = 0;
  57. for (; blank(ch); ch = nc());
  58. if (IOerror)return;
  59. if (ch == '-')sign = 1, ch = nc();
  60. for (; ch >= '0'&&ch <= '9'; ch = nc())x = x * 10 + ch - '0';
  61. if (ch == '.') {
  62. double tmp = 1; ch = nc();
  63. for (; ch >= '0'&&ch <= '9'; ch = nc())tmp /= 10.0, x += tmp * (ch - '0');
  64. }
  65. if (sign)x = -x;
  66. }
  67. inline void read(char *s) {
  68. char ch = nc();
  69. for (; blank(ch); ch = nc());
  70. if (IOerror)return;
  71. for (; !blank(ch) && !IOerror; ch = nc())*s++ = ch;
  72. *s = 0;
  73. }
  74. inline void read(char &c) {
  75. for (c = nc(); blank(c); c = nc());
  76. if (IOerror) { c = -1; return; }
  77. }
  78. //fwrite->write
  79. struct Ostream_fwrite {
  80. char *buf, *p1, *pend;
  81. Ostream_fwrite() { buf = new char[BUF_SIZE]; p1 = buf; pend = buf + BUF_SIZE; }
  82. void out(char ch) {
  83. if (p1 == pend) {
  84. fwrite(buf, 1, BUF_SIZE, stdout); p1 = buf;
  85. }
  86. *p1++ = ch;
  87. }
  88. void print(int x) {
  89. static char s[15], *s1; s1 = s;
  90. if (!x)*s1++ = '0'; if (x<0)out('-'), x = -x;
  91. while (x)*s1++ = x % 10 + '0', x /= 10;
  92. while (s1-- != s)out(*s1);
  93. }
  94. void println(int x) {
  95. static char s[15], *s1; s1 = s;
  96. if (!x)*s1++ = '0'; if (x<0)out('-'), x = -x;
  97. while (x)*s1++ = x % 10 + '0', x /= 10;
  98. while (s1-- != s)out(*s1); out('\n');
  99. }
  100. void print(ll x) {
  101. static char s[25], *s1; s1 = s;
  102. if (!x)*s1++ = '0'; if (x<0)out('-'), x = -x;
  103. while (x)*s1++ = x % 10 + '0', x /= 10;
  104. while (s1-- != s)out(*s1);
  105. }
  106. void println(ll x) {
  107. static char s[25], *s1; s1 = s;
  108. if (!x)*s1++ = '0'; if (x<0)out('-'), x = -x;
  109. while (x)*s1++ = x % 10 + '0', x /= 10;
  110. while (s1-- != s)out(*s1); out('\n');
  111. }
  112. void print(double x, int y) {
  113. static ll mul[] = { 1,10,100,1000,10000,100000,1000000,10000000,100000000,
  114. 1000000000,10000000000LL,100000000000LL,1000000000000LL,10000000000000LL,
  115. 100000000000000LL,1000000000000000LL,10000000000000000LL,100000000000000000LL };
  116. if (x<-1e-12)out('-'), x = -x; x *= mul[y];
  117. ll x1 = (ll)floor(x); if (x - floor(x) >= 0.5)++x1;
  118. ll x2 = x1 / mul[y], x3 = x1 - x2 * mul[y]; print(x2);
  119. if (y>0) { out('.'); for (size_t i = 1; i<y&&x3*mul[i]<mul[y]; out('0'), ++i); print(x3); }
  120. }
  121. void println(double x, int y) { print(x, y); out('\n'); }
  122. void print(char *s) { while (*s)out(*s++); }
  123. void println(char *s) { while (*s)out(*s++); out('\n'); }
  124. void flush() { if (p1 != buf) { fwrite(buf, 1, p1 - buf, stdout); p1 = buf; } }
  125. ~Ostream_fwrite() { flush(); }
  126. }Ostream;
  127. inline void print(int x) { Ostream.print(x); }
  128. inline void println(int x) { Ostream.println(x); }
  129. inline void print(char x) { Ostream.out(x); }
  130. inline void println(char x) { Ostream.out(x); Ostream.out('\n'); }
  131. inline void print(ll x) { Ostream.print(x); }
  132. inline void println(ll x) { Ostream.println(x); }
  133. inline void print(double x, int y) { Ostream.print(x, y); }
  134. inline void println(double x, int y) { Ostream.println(x, y); }
  135. inline void print(char *s) { Ostream.print(s); }
  136. inline void println(char *s) { Ostream.println(s); }
  137. inline void println() { Ostream.out('\n'); }
  138. inline void flush() { Ostream.flush(); }
  139. #undef ll
  140. #undef OUT_SIZE
  141. #undef BUF_SIZE
  142. };
  143. using namespace IO;
  144. void init()
  145. {
  146. e = 0; curID = 0;
  147. memset(head,-1,sizeof(head));
  148. memset(red,0,sizeof(red));
  149. }
  150. void AddEdge (int u,int v,LL w)
  151. {
  152. edges[e].v=v;
  153. edges[e].dis=w;
  154. edges[e].next=head[u];
  155. head[u]=e++;
  156. }
  157. void DFS (int u,int p,int Dep,LL d)
  158. {
  159. int i,v;
  160. if(red[u]) d=0;
  161. curID++;
  162. rdis[u] = d;
  163. F[curID]=u;
  164. B[curID]=Dep;
  165. id[u]=curID;
  166. for (i=head[u];i!=-1;i=edges[i].next){
  167. v=edges[i].v;
  168. if (v==p) continue;
  169. dis[v]=dis[u] + edges[i].dis;
  170. DFS(v,u,Dep+1,d+edges[i].dis);
  171. curID++;
  172. F[curID]=u;
  173. B[curID]=Dep;
  174. }
  175. }
  176. void initRMQ ()
  177. {
  178. int i,j,x,y;
  179. for (i=1;i<=curID;i++)
  180. RMQ[i][0]=i;
  181. for (j=1;(1<<j)<=curID;j++)
  182. for (i=1;i+(1<<j)-1<=curID;i++){
  183. x=RMQ[i][j-1];
  184. y=RMQ[i+(1<<(j-1))][j-1];
  185. RMQ[i][j]=B[x]<B[y]?x:y;
  186. }
  187. }
  188. int getLCA (int a,int b)
  189. {
  190. int k,x,y;
  191. a=id[a];b=id[b];
  192. if (a>b)
  193. k=a,a=b,b=k;
  194. k = 31 - __builtin_clz(b-a+1);
  195. x=RMQ[a][k];
  196. y=RMQ[b-(1<<k)+1][k];
  197. return B[x]<B[y]?F[x]:F[y];
  198. }
  199. int qq[N],cnt;
  200. int vz[N];
  201. bool check(LL &x)
  202. {
  203. int all =0;
  204. for(int i=0;i<cnt;++i){ //枚举超过限制的结点
  205. if(rdis[qq[i]]>x){
  206. vz[all++] = qq[i];
  207. }
  208. }
  209. if(all==0) return true;
  210. int lca = vz[0];
  211. for(int i=0;i<all;++i){ //求出所有非法结点的lca,这个lca就是要染色的点
  212. lca = getLCA(lca,vz[i]);
  213. }
  214. LL mx = 0;
  215. for(int i=0;i<all;++i){ //查看最长距离
  216. if(dis[vz[i]]-dis[lca]>x) return false;
  217. }
  218. return true;
  219. }
  220. int main()
  221. {
  222. #ifndef ONLINE_JUDGE
  223. freopen("in.txt","r",stdin);
  224. freopen("out.txt","w",stdout);
  225. #endif
  226. int T; read(T);
  227. while(T--){
  228. int n,M,Q;
  229. int u,v; LL w;
  230. LL up = 0;
  231. init();
  232. read(n), read(M), read(Q);
  233. //scanf("%d %d %d",&n,&M,&Q);
  234. for(int i=1;i<=M;++i){
  235. read(u);
  236. red[u] = 1;
  237. }
  238. red[1] = 1;
  239. for(int i=1;i<n;++i){
  240. //scanf("%d %d %lld",&u,&v,&w);
  241. read(u), read(v), read(w);
  242. AddEdge(u,v,w);
  243. AddEdge(v,u,w);
  244. up += w;
  245. }
  246. DFS(1,0,0,0);
  247. initRMQ();
  248. while(Q--){
  249. int k; read(k);//scanf("%d",&k);
  250. cnt = k;
  251. for(int i=0;i<k;++i){
  252. read(qq[i]);
  253. //scanf("%d",&qq[i]);
  254. }
  255. LL L =0,R = up,mid,ans = up;
  256. while(L<=R){
  257. mid = (L+R)>>1;
  258. if(check(mid)){
  259. ans = mid;
  260. R = mid-1;
  261. }
  262. else L =mid+1;
  263. }
  264. println(ans);
  265. //printf("%lld\n",ans);
  266. }
  267. }
  268. return 0;
  269. }

ZOJ - 4048 Red Black Tree (LCA+贪心) The 2018 ACM-ICPC Asia Qingdao Regional Contest, Online的更多相关文章

  1. UVALive 7146 Defeat the Enemy(贪心+STL)(2014 Asia Shanghai Regional Contest)

    Long long ago there is a strong tribe living on the earth. They always have wars and eonquer others. ...

  2. HDU 3697 Selecting courses(贪心+暴力)(2010 Asia Fuzhou Regional Contest)

    Description     A new Semester is coming and students are troubling for selecting courses. Students ...

  3. The 2019 ICPC Asia Shanghai Regional Contest H Tree Partition k、Color Graph

    H题意: 给你一个n个节点n-1条无向边构成的树,每一个节点有一个权值wi,你需要把这棵树划分成k个子树,每一个子树的权值是这棵子树上所有节点权值之和. 你要输出这k棵子树的权值中那个最大的.你需要让 ...

  4. HDU 4757 Tree(可持久化字典树)(2013 ACM/ICPC Asia Regional Nanjing Online)

    Problem Description   Zero and One are good friends who always have fun with each other. This time, ...

  5. ZOJ 4062 - Plants vs. Zombies - [二分+贪心][2018 ACM-ICPC Asia Qingdao Regional Problem E]

    题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=4062 题意: 现在在一条 $x$ 轴上玩植物大战僵尸,有 $n$ ...

  6. ZOJ 4067 - Books - [贪心][2018 ACM-ICPC Asia Qingdao Regional Problem J]

    题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=4067 题意: 给出 $n$ 本书(编号 $1 \sim n$), ...

  7. HDU 5458 Stability(双连通分量+LCA+并查集+树状数组)(2015 ACM/ICPC Asia Regional Shenyang Online)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5458 Problem Description Given an undirected connecte ...

  8. UVALive 7147 World Cup(数学+贪心)(2014 Asia Shanghai Regional Contest)

    题目链接:https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&category=6 ...

  9. HDU 5002 Tree(动态树LCT)(2014 ACM/ICPC Asia Regional Anshan Online)

    Problem Description You are given a tree with N nodes which are numbered by integers 1..N. Each node ...

随机推荐

  1. Loadrunner测试实例分析

    LoadRunner性能测试结果分析是个复杂的过程,通常可以从结果摘要.并发数.平均事务响应时间.每秒点击数.业务成功率.系统资源.网页细分图.Web服务器资源.数据库服务器资源等几个方面分析,如图1 ...

  2. 集成学习AdaBoost算法——学习笔记

    集成学习 个体学习器1 个体学习器2 个体学习器3   ——> 结合模块  ——>输出(更好的) ... 个体学习器n 通常,类似求平均值,比最差的能好一些,但是会比最好的差. 集成可能提 ...

  3. C# 直接调用非托管代码的方法

    C# 代码有以下两种可以直接调用非托管代码的方法: 直接调用从 DLL 导出的函数. 调用 COM 对象上的接口方法. 对于这两种技术,都必须向 C# 编译器提供非托管函数的声明,并且还可能需要向 C ...

  4. iOS开发之-- 抢购、距活动结束,剩余时间倒计时

    因为没有时间去着重研究过这个东西,只是知道大体上的逻辑,就是两个时间才行比对,具体的实现也是参考别人的写的方法, 只是做个记录,有时间会好好看看这个东西,具体代码如下: /** * 倒计时 * * @ ...

  5. 用vue2.0实现点击选中active,其他选项互斥的效果

    在正常的js中.我们如果要实现点击选中active然后其他取消的效果,我们可以定义一个类,当点击的时候给给多有的dom取消active的类,给当前元素加上这个类名,说的很啰嗦,直接来看代码说话吧(表示 ...

  6. jquery remove() detach() empty()三种方法的区别

    remove方法把事件删除掉了,数据并没有删除 detach方法保存了事件和数据 empty方法保留了元素本身,移除子节点,删除内容 举例: <!DOCTYPE html><html ...

  7. 170411、java Socket通信的简单例子(UDP)

    服务端代码: package com.bobohe.socket; import java.io.*; import java.net.*; class UDPServer { public stat ...

  8. Exception in thread "main" java.lang.UnsupportedClassVersionError: * : Unsupported major.minor version 52.0 解决办法

    Exception in thread "main" java.lang.UnsupportedClassVersionError: * : Unsupported major.m ...

  9. 前端开发 - JQuery - 下

    二十五.jquery的事件 <!DOCTYPE html> <html lang="en"> <head> <meta charset=& ...

  10. 前端开发 - CSS - 上

    CSS: 1.css的引入方式 2.基础选择器 3.高级选择器 4.选择器的优先级 5.伪类选择器 6.字体样式 7.文本样式 8.背景 9.盒模型border 10.margin 11.paddin ...