spoj题面

Time limit 433 ms //spoj的时限都那么奇怪

Memory limit 1572864 kB //1.5个G,疯了

Code length Limit 15000 B

OS Linux

Language limit All except: ERL JS-RHINO NODEJS PERL6 VB.NET

Source Special thanks to Ivan Krasilnikov for his alternative solution

Author Thanh-Vy Hua

吐槽

期中考第二个能A的题,结果写了半个小时,调了一个半小时……纪念一下第二道被多组Case读入害死的题目……这题是把下一个case的前两个数读进来了,那一次是这次的case没读完就进入下一个case了,这才过了两个星期啊……下次测这种样例就该把样例多复制几遍……

顺便吐槽,这是啥数据啊……一步一步地向上暴力跳都能A,亏我还跳重链……而且case之间加空行这个要求它不会判,加不加空行都是AC

解题思路

我一看见这题就没多想,直接上树链剖分,结果写完反应过来杀鸡用牛刀,这题dfs预处理一遍,倍增跳树并统计结果是更优的办法,代码可以短不少。

树链剖分处理\(KTH\)操作是利用了一个性质:一条重链上的节点新id,从上到下是连续的,所以跳链的时候如果发现跳过了目标\(k\),那么就直接使用这条重链两端的新\(id\)计算出目标\(k\)的\(id\),然后转换成原来的的编号即可。另外,由于这题路径有了方向,所以跳链的时候不能像平时那样std::swap(u,v),而是要判断应该跳u还是跳v,然后分情况写。

源代码

  1. #include<stdio.h>
  2. #include<string.h>
  3. #include<algorithm>
  4. int T;
  5. int n;
  6. struct Edge{
  7. int nxt,to,w;
  8. }e[200010];
  9. int head[100010],cnt;
  10. void add(int u,int v,int w)
  11. {
  12. e[cnt]={head[u],v,w};
  13. head[u]=cnt++;
  14. e[cnt]={head[v],u,w};
  15. head[v]=cnt++;
  16. }
  17. struct Tree{
  18. int fa,dep,w,sz,wson;
  19. int top,id;
  20. }t[100010];
  21. void dfs1(int fa,int u,int w)
  22. {
  23. t[u].fa=fa;
  24. t[u].dep=t[fa].dep+1;
  25. t[u].w=w;
  26. t[u].sz=1;
  27. int maxn=0;
  28. for(int i=head[u];i;i=e[i].nxt)
  29. {
  30. int v=e[i].to;
  31. if(v==fa) continue;
  32. dfs1(u,v,e[i].w);
  33. int temp=t[v].sz;
  34. t[u].sz+=temp;
  35. if(temp>maxn)
  36. {
  37. maxn=temp;
  38. t[u].wson=v;
  39. }
  40. }
  41. }
  42. int id=1;
  43. int mp[100010];//用新id查询老id
  44. long long a[100010];
  45. void dfs2(int u,int top)
  46. {
  47. t[u].top=top;
  48. t[u].id=id;
  49. a[id]=t[u].w;
  50. mp[id]=u;
  51. id++;
  52. if(t[u].sz==1) return;
  53. dfs2(t[u].wson,top);
  54. for(int i=head[u];i;i=e[i].nxt)
  55. {
  56. int v=e[i].to;
  57. if(v==t[u].fa||v==t[u].wson) continue;
  58. dfs2(v,v);
  59. }
  60. }
  61. long long sum[400010];//线段树维护区间和
  62. void build(int x,int l,int r)
  63. {
  64. if(l==r)
  65. {
  66. sum[x]=a[l];
  67. return;
  68. }
  69. int mid=l+r>>1;
  70. build(x<<1,l,mid);
  71. build(x<<1|1,mid+1,r);
  72. sum[x]=sum[x<<1]+sum[x<<1|1];
  73. }
  74. long long quesum(int x,int l,int r,int ql,int qr)
  75. {
  76. if(qr<ql) return 0;
  77. if(ql<=l&&r<=qr) return sum[x];
  78. int mid=l+r>>1;
  79. long long ans=0;
  80. if(ql<=mid) ans+=quesum(x<<1,l,mid,ql,qr);
  81. if(qr>mid) ans+=quesum(x<<1|1,mid+1,r,ql,qr);
  82. return ans;
  83. }
  84. long long dist(int u,int v)
  85. {
  86. long long ans=0;
  87. while(t[u].top!=t[v].top)
  88. {
  89. if(t[t[u].top].dep<t[t[v].top].dep) std::swap(u,v);
  90. ans+=quesum(1,1,n,t[t[u].top].id,t[u].id);
  91. u=t[t[u].top].fa;
  92. }
  93. if(t[u].id>t[v].id) std::swap(u,v);
  94. ans+=quesum(1,1,n,t[u].id+1,t[v].id);
  95. return ans;
  96. }
  97. int kth(int ss,int tt,int k)//要区分起点和终点
  98. {
  99. int num=0;
  100. int u=ss,v=tt;//先跳一遍找到总的点数
  101. while(t[u].top!=t[v].top)
  102. {
  103. if(t[t[u].top].dep<t[t[v].top].dep) std::swap(u,v);
  104. num+=t[u].id-t[t[u].top].id+1;//这条重链
  105. u=t[t[u].top].fa;
  106. }
  107. if(t[u].id>t[v].id) std::swap(u,v);
  108. num+=t[v].id-t[u].id+1;
  109. while(t[ss].top!=t[tt].top)//跳链找答案
  110. {
  111. if(t[t[ss].top].dep<t[t[tt].top].dep)//跳tt点
  112. {
  113. int temp=t[tt].id-t[t[tt].top].id+1;//重链长度
  114. if(num-temp<k)//跳过了
  115. {
  116. return mp[t[tt].id-(num-k)];
  117. }
  118. else//还在上方,num减少
  119. {
  120. num-=temp;
  121. tt=t[t[tt].top].fa;
  122. }
  123. }
  124. else//跳ss点
  125. {
  126. int temp=t[ss].id-t[t[ss].top].id+1;
  127. if(k<=temp)//找到了
  128. {
  129. return mp[t[ss].id-k+1];
  130. }
  131. else//还在上方
  132. {
  133. k-=temp;
  134. num-=temp;
  135. ss=t[t[ss].top].fa;
  136. }
  137. }
  138. }
  139. //跳到同一条链上了。
  140. if(t[ss].dep<t[tt].dep)
  141. return mp[t[ss].id+k-1];
  142. else
  143. return mp[t[ss].id-k+1];
  144. }
  145. int main()
  146. {
  147. //freopen("test.in","r",stdin);
  148. scanf("%d",&T);
  149. while(T--)
  150. {
  151. scanf("%d",&n);
  152. memset(head,0,sizeof(int)*(n+2));
  153. cnt=id=1;
  154. for(int i=1,u,v,w;i<n;i++)
  155. {
  156. scanf("%d%d%d",&u,&v,&w);
  157. add(u,v,w);
  158. }
  159. dfs1(0,1,0);
  160. dfs2(1,1);
  161. build(1,1,n);
  162. while(1)
  163. {
  164. char opt[10];
  165. int u,v,k;
  166. scanf("%s",opt);//开始我写了个%s%d%d,opt,&u,&v……
  167. if(opt[1]=='I')
  168. {
  169. scanf("%d%d",&u,&v);
  170. printf("%lld\n",dist(u,v));
  171. }
  172. else if(opt[1]=='T')
  173. {
  174. scanf("%d%d%d",&u,&v,&k);
  175. printf("%d\n",kth(u,v,k));
  176. }
  177. else break;
  178. }
  179. puts("");//空行加不加都可以A
  180. }
  181. return 0;
  182. }

SPOJ 913 Query on a tree II的更多相关文章

  1. spoj 913 Query on a tree II (倍增lca)

    Query on a tree II You are given a tree (an undirected acyclic connected graph) with N nodes, and ed ...

  2. QTREE2 spoj 913. Query on a tree II 经典的倍增思想

    QTREE2 经典的倍增思想 题目: 给出一棵树,求: 1.两点之间距离. 2.从节点x到节点y最短路径上第k个节点的编号. 分析: 第一问的话,随便以一个节点为根,求得其他节点到根的距离,然后对于每 ...

  3. SPOJ QTREE2 Query on a tree II

    传送门 倍增水题…… 本来还想用LCT做的……然后发现根本不需要 //minamoto #include<bits/stdc++.h> using namespace std; #defi ...

  4. 【SPOJ】Count On A Tree II(树上莫队)

    [SPOJ]Count On A Tree II(树上莫队) 题面 洛谷 Vjudge 洛谷上有翻译啦 题解 如果不在树上就是一个很裸很裸的莫队 现在在树上,就是一个很裸很裸的树上莫队啦. #incl ...

  5. 【BZOJ2589】 Spoj 10707 Count on a tree II

    BZOJ2589 Spoj 10707 Count on a tree II Solution 吐槽:这道题目简直...丧心病狂 如果没有强制在线不就是树上莫队入门题? 如果加了强制在线怎么做? 考虑 ...

  6. LCA SP913 QTREE2 - Query on a tree II

    SP913 QTREE2 - Query on a tree II 给定一棵n个点的树,边具有边权.要求作以下操作: DIST a b 询问点a至点b路径上的边权之和 KTH a b k 询问点a至点 ...

  7. SPOJ COT2 - Count on a tree II(LCA+离散化+树上莫队)

    COT2 - Count on a tree II #tree You are given a tree with N nodes. The tree nodes are numbered from  ...

  8. SPOJ 375. Query on a tree (树链剖分)

    Query on a tree Time Limit: 5000ms Memory Limit: 262144KB   This problem will be judged on SPOJ. Ori ...

  9. SPOJ QTREE Query on a tree 树链剖分+线段树

    题目链接:http://www.spoj.com/problems/QTREE/en/ QTREE - Query on a tree #tree You are given a tree (an a ...

随机推荐

  1. Anko

    先mark一下. https://www.jianshu.com/p/4a3ca2c315f2

  2. MySQL-4- 索引及执行计划

    1. 索引作用 提供了类似于书中目录的作用,目的是为了优化查询 2. 索引的种类(算法) B树索引 Hash索引 R树 Full text GIS 3. B树 基于不同的查找算法分类介绍   B-tr ...

  3. java_第一年_JDBC(1)

    JDBC(Java Data Base Connectivity),用于实现java语言编程与数据库连接的API. 数据库驱动:应用程序并不能直接使用数据库,而需要通过相应的数据库驱动程序后再操作数据 ...

  4. mysql自增主键字段重排

    不带外键模式的 mysql 自增主键字段重排 1.备份表结构 create table table_bak like table_name; 2.备份表数据 insert into table_bak ...

  5. python之入门

    第一章 入门 1.1 变量-输出 a = 1 # 声明变量 a # 变量的名字 = # 赋值 1 # 值 变量定义的规则: 1.变量由数字,字母,下划线组成 2.不能以数字开头 3.不能使用pytho ...

  6. numpy-数据格式之 int 与 uint

    概念 整型分为 有符号整型 和 无符号整型,其区别在于 无符号整型 可以存放的正数范围 比 有符号整型 大一倍,因为 有符号整型  将最高位存储符号,而 无符号整型 全部存储数字 # 1 111000 ...

  7. 帝国cms 项目搬家换域名修改详情页图片路径

    update phome_ecms_news_data_1 set newstext=REPLACE (newstext,'/d/file/','http://www.xxxx.com/d/file/ ...

  8. 【leetcode】 463. Island Perimeter

    题目: 以二维数组形式表示坐标岛屿,求边长. 例子: [[0,1,0,0], [1,1,1,0], [0,1,0,0], [1,1,0,0]] Answer: 16 Explanation: The ...

  9. Redis5以上版本伪集群搭建(高可用集群模式)

    redis集群需要至少要三个master节点,我们这里搭建三个master节点,并且给每个master再搭建一个slave节点,总共6个redis节点,这里用一台机器(可以多台机器部署,修改一下ip地 ...

  10. redis windows相关操作笔记

    设置远程访问 1.注释掉bind 127.0.0.1. 2.protected-mode属性从yes改为no. 启动redis服务:redis-server.exe redis.windows.con ...