先一道一道题慢慢补上,

1009.题意,一棵N(N<=50000)个节点的树,每个节点上有一个字母值,给定一个串S0(|S0| <=30),q个询问,(q<=50000),每次询问经过两个点u,v之间的路径上的字母构成字符串S,问S0在S中作为序列出现了多少次。

分析:对于每次询问需要知道其LCA,设w = LCA(u, v),可以用tarjan处理出来,或者倍增法也行。然后w会将S0分成两部分,记做S1,S2,然后分别考虑S1在u->w的路径出现次数,以及S2在v->w出现的次数。

S1(x) = S0[1....x],1<=x<=|S0|.

以S1为例,需要预处理出来u到根节点的路径上对应S0[i,j]序列出现的次数,设为dp1[u][i][j],然后S1(x)在u->w出现的次数记为t1[x],那么

t1[x] = dp1[u][1][x] - sum{t1[a-1]*dp1[fa[w]][a][x]} (1<=a<=x)

而dp1[u][1][x] 可以在tarjan求LCA时候预处理出来,转移dp1[u][i][j] = dp1[fa[u]][i][j] + (nd[u] == S0[i])*dp1[fa[u]][i+1][j];

对于S2也是可以同样考虑的。

注意:占用内存很大,需要用16位节省内存,dfs的话还需要扩栈,实现时发现不能随便用unsigned short,因为变成负数的话会相当于mod 2^16这个是会导致WA的。

代码:

  1. #pragma comment(linker, "/STACK:16777216")
  2. #include <cstdio>
  3. #include <iostream>
  4. #include <cstring>
  5. #include <string>
  6. #include <cstdlib>
  7. #include <algorithm>
  8. #include <vector>
  9. #include <queue>
  10. #include <map>
  11. #include <set>
  12. #define in freopen("solve_in.txt", "r", stdin);
  13. #define Rep(i, base, n) for(int i = (base); i < n; i++)
  14. #define REP(i, n) for(int i = 0; i < (n); i++)
  15. #define VREP(i, n, base) for(int i = (n); i >= (base); i--)
  16. #define SET(a, n) memset(a, (n), sizeof(a));
  17. #define pb push_back
  18. #define mp make_pair
  19.  
  20. using namespace std;
  21. typedef vector<unsigned short> VI;
  22. typedef pair<unsigned short, unsigned short> PII;
  23. typedef vector<PII> VII;
  24. typedef long long LL;
  25.  
  26. const int maxn = + ;
  27. const int maxm = ;
  28. const int M = ;
  29.  
  30. short dp1[maxn][maxm][maxm], dp2[maxn][maxm][maxm];
  31. bool vis[maxn];
  32. int len;
  33. char s[maxm], nd[maxn];
  34. unsigned short pa[maxn];
  35.  
  36. VI g[maxn];
  37. unsigned short lca[maxn];
  38. VII que[maxn];
  39. VII qq;
  40.  
  41. unsigned short findset(unsigned short x) {
  42. return x == pa[x] ? x : pa[x] = findset(pa[x]);
  43. }
  44.  
  45. void init(int n) {
  46. qq.clear();
  47. REP(i, n+) {
  48. que[i].clear();
  49. g[i].clear();
  50. vis[i] = false;
  51. REP(j, maxm) REP(k, maxm) {
  52. dp1[i][j][k] = , dp2[i][j][k] = ;
  53. if(j > k)
  54. dp1[i][j][k] = ;
  55. if(j < k)
  56. dp2[i][j][k] = ;
  57. }
  58. }
  59. }
  60. int n, m;
  61. short t1[maxm], t2[maxm];
  62. void tarjan(int u, int fa) {
  63. pa[u] = u;
  64. if(!fa) {
  65. Rep(i, , len+)
  66. if(s[i] == nd[u]) {
  67. dp1[u][i][i] = dp2[u][i][i] = ;
  68. }
  69. } else {
  70. int v = u;
  71. u = fa;
  72. Rep(i, , len+) Rep(j, , len+) {
  73. if(i >= j) {
  74. dp2[v][i][j] = (dp2[v][i][j] + dp2[u][i][j] + (nd[v] == s[i])*(dp2[u][i-][j]))%M;
  75. }
  76. if(dp2[v][i][j] < )
  77. dp2[v][i][j] += M;
  78. if(i <= j) {
  79. dp1[v][i][j] = (dp1[v][i][j] + dp1[u][i][j] + (nd[v] == s[i])*(dp1[u][i+][j]))%M;
  80. }
  81. if(dp1[v][i][j] < )
  82. dp1[v][i][j] += M;
  83. }
  84. u =v;
  85. }
  86. vis[u] = true;
  87. REP(i, g[u].size()) {
  88. int v = g[u][i];
  89. if(v == fa)
  90. continue;
  91. tarjan(v, u);
  92. pa[v] = u;
  93. }
  94. REP(i, que[u].size()) {
  95. int v = que[u][i].first;
  96. int id = que[u][i].second;
  97. if(!vis[v])
  98. continue;
  99. lca[id] = findset(v);
  100. }
  101. }
  102. void solve() {
  103. REP(ii, m) {
  104. int w = lca[ii];
  105. int u = qq[ii].first;
  106. int v = qq[ii].second;
  107. if(u == v) {
  108. printf("%d\n", len == && s[] == nd[u]);
  109. continue;
  110. }
  111. SET(t1, );
  112. SET(t2, );
  113. t1[] = t2[len+] = ;
  114. if(w != u) {
  115. Rep(i, , len+) {
  116. int tmp = ;
  117. Rep(x, , i+) {
  118. tmp = (tmp + ((LL)t1[x-]*dp1[w][x][i])%M)%M;
  119. }
  120. t1[i] = (dp1[u][][i]-tmp)%M;
  121. if(t1[i] < )
  122. t1[i] += M;
  123. }
  124. }
  125. if(w != v) {
  126. VREP(i, len, ) {
  127. int tmp = ;
  128. VREP(x, len, i) {
  129. tmp = (tmp + ((LL)t2[x+]*dp2[w][x][i])%M)%M;
  130. }
  131. t2[i] = (dp2[v][len][i] - tmp)%M;
  132. if(t2[i] < )
  133. t2[i] += M;
  134. }
  135. }
  136. int ans = ;
  137. REP(i, len+) {
  138. if(s[i] == nd[w])
  139. ans = (ans + ((LL)t1[i-]*t2[i+])%M)%M;
  140. ans = (ans + ((LL)t1[i]*t2[i+])%M)%M;
  141. if(ans < )
  142. ans += M;
  143. }
  144. if(ans < )
  145. ans += M;
  146. printf("%d\n", ans);
  147. }
  148. }
  149. int main() {
  150.  
  151. int T;
  152. for(int t = scanf("%d", &T); t <= T; t++) {
  153. scanf("%d%d", &n, &m);
  154. init(n);
  155. REP(i, n-) {
  156. int u, v;
  157. scanf("%d%d", &u, &v);
  158. g[u].pb(v);
  159. g[v].pb(u);
  160. }
  161. s[] = '\0';
  162. scanf("%s%s", nd+, s+);
  163. len = strlen(s+);
  164. REP(i, m) {
  165. int u, v;
  166. scanf("%d%d", &u, &v);
  167. qq.pb(mp(u, v));
  168. que[u].pb(mp(v, i));
  169. que[v].pb(mp(u, i));
  170. }
  171. tarjan(, );
  172. solve();
  173. }
  174. return ;
  175. }

HDOJ多校联合第六场的更多相关文章

  1. HDU 5793 A Boring Question (逆元+快速幂+费马小定理) ---2016杭电多校联合第六场

    A Boring Question Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others ...

  2. HDU 5795 A Simple Nim (博弈) ---2016杭电多校联合第六场

    A Simple Nim Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Tota ...

  3. HDOJ多校联合第五场

    1001 Inversion 题意:求逆序对,然后交换k次相邻的两个数,使得剩下的逆序对最少. 分析:题目用到的结论是:数组中存在一对逆序对,那么可以通过交换相邻两个数使得逆序对减少1,交换k次,可以 ...

  4. HDOJ多校联合第四场

    B题: C题:仅由'A','G','C','T',4个字母组成,给定一个字符串S,|S|<=15,给定一个整数m,以m为长度且仅含4种字母的字符串T,求LCS(S,T)为0,1,2,3....| ...

  5. hdu5379||2015多校联合第7场1011 树形统计

    pid=5379">http://acm.hdu.edu.cn/showproblem.php? pid=5379 Problem Description Little sun is ...

  6. HDU 5831 Rikka with Parenthesis II (贪心) -2016杭电多校联合第8场

    题目:传送门. 题意:T组数据,每组给定一个长度n,随后给定一个长度为n的字符串,字符串只包含'('或')',随后交换其中两个位置,必须交换一次也只能交换一次,问能否构成一个合法的括号匹配,就是()( ...

  7. HDU 5821 Ball (贪心排序) -2016杭电多校联合第8场

    题目:传送门. 题意:T组数据,每组给定一个n一个m,在给定两个长度为n的数组a和b,再给定m次操作,每次给定l和r,每次可以把[l,r]的数进行任意调换位置,问能否在转换后使得a数组变成b数组. 题 ...

  8. HDU 5762 Teacher Bo (鸽笼原理) 2016杭电多校联合第三场

    题目:传送门. 题意:平面上有n个点,问是否存在四个点 (A,B,C,D)(A<B,C<D,A≠CorB≠D)使得AB的横纵坐标差的绝对值的和等于CD的横纵坐标差的绝对值的和,n<1 ...

  9. HDU 5752 Sqrt Bo (思维题) 2016杭电多校联合第三场

    题目:传送门. 题意:一个很大的数n,最多开5次根号,问开几次根号可以得到1,如果5次还不能得到1就输出TAT. 题解:打表题,x1=1,x2=(x1+1)*(x1+1)-1,以此类推.x5是不超过l ...

随机推荐

  1. linux文件系统评估之inode

    存储系统上线前要做资源评估,通常需要在性能(即iops.带宽等)和容量维度进行业务评估:而具体到本地文件系统存储的容量时,需要根据具体业务对文件系统的可用数据空间和可用inode数进行评估,作者通过工 ...

  2. Oracle连接配置以及实例的备份和恢复

    背景:一个团队项目开发,不可能每个人都架设自己本地的数据库,大多数情况下是统一用服务器上的数据库,这时候就需要进行远程数据库的连接.而且有时候还需要进行数据库搬迁 ,这时候就需要进行数据库的备份和恢复 ...

  3. jQuery 源码分析 7: sizzle

    jQuery使用的是sizzle这个选择器引擎,这个引擎以其高速著称,其实现十分精妙但是也足够复杂,下面现简单分析一下相关的代码. 在jQuery的部分API接口是直接引用了Sizzle的方法,这些接 ...

  4. 16_会话技术_Session案例

    [购物车中的信息保存] [Book.java] package com.Higgin.shopping; public class Book { private String id; private ...

  5. (CodeForces 510C) Fox And Names 拓扑排序

    题目链接:http://codeforces.com/problemset/problem/510/C Fox Ciel is going to publish a paper on FOCS (Fo ...

  6. java.util.AbstractStringBuilder源码分析

    AbstractStringBuilder是一个抽象类,是StringBuilder和StringBuffer的父类,分析它的源码对StringBuilder和StringBuffer代码的理解有很大 ...

  7. mysql与Navicat for MySQL的衔接配置问题【原创】

    首先改一下php的配置文件: 这里主要该两个地方:Cirl + F 查找到mysql.dll 然后去掉前面的";" 然后是修改路径:Cirl + F 查找到extension_di ...

  8. 简单改造 starling 中的 AssetManager 让其更适合 批次加载纹理

    API文档参考:http://doc.starling-framework.org/core/starling/utils/AssetManager.html 项目想以不改动starling的情况下对 ...

  9. DataNavigator之分页

    前言 做客户端也有两个月了,先前做列表都没有分页,可能考虑数据也不是很多,昨天做了一个页面,考虑到了数据的问题,所以改为分页查询.因为也是第一次用dev,用哪个控件分页呢,还是要去搜一下,得出的事Da ...

  10. 重新开始学习c#啦,希望能坚持下去!

    过了这么多年,还是感觉自己喜欢C#,喜欢编程,虽然自己什么技术也没有:做的项目也不算是项目: