先一道一道题慢慢补上,

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的。

代码:

 #pragma comment(linker, "/STACK:16777216")
#include <cstdio>
#include <iostream>
#include <cstring>
#include <string>
#include <cstdlib>
#include <algorithm>
#include <vector>
#include <queue>
#include <map>
#include <set>
#define in freopen("solve_in.txt", "r", stdin);
#define Rep(i, base, n) for(int i = (base); i < n; i++)
#define REP(i, n) for(int i = 0; i < (n); i++)
#define VREP(i, n, base) for(int i = (n); i >= (base); i--)
#define SET(a, n) memset(a, (n), sizeof(a));
#define pb push_back
#define mp make_pair using namespace std;
typedef vector<unsigned short> VI;
typedef pair<unsigned short, unsigned short> PII;
typedef vector<PII> VII;
typedef long long LL; const int maxn = + ;
const int maxm = ;
const int M = ; short dp1[maxn][maxm][maxm], dp2[maxn][maxm][maxm];
bool vis[maxn];
int len;
char s[maxm], nd[maxn];
unsigned short pa[maxn]; VI g[maxn];
unsigned short lca[maxn];
VII que[maxn];
VII qq; unsigned short findset(unsigned short x) {
return x == pa[x] ? x : pa[x] = findset(pa[x]);
} void init(int n) {
qq.clear();
REP(i, n+) {
que[i].clear();
g[i].clear();
vis[i] = false;
REP(j, maxm) REP(k, maxm) {
dp1[i][j][k] = , dp2[i][j][k] = ;
if(j > k)
dp1[i][j][k] = ;
if(j < k)
dp2[i][j][k] = ;
}
}
}
int n, m;
short t1[maxm], t2[maxm];
void tarjan(int u, int fa) {
pa[u] = u;
if(!fa) {
Rep(i, , len+)
if(s[i] == nd[u]) {
dp1[u][i][i] = dp2[u][i][i] = ;
}
} else {
int v = u;
u = fa;
Rep(i, , len+) Rep(j, , len+) {
if(i >= j) {
dp2[v][i][j] = (dp2[v][i][j] + dp2[u][i][j] + (nd[v] == s[i])*(dp2[u][i-][j]))%M;
}
if(dp2[v][i][j] < )
dp2[v][i][j] += M;
if(i <= j) {
dp1[v][i][j] = (dp1[v][i][j] + dp1[u][i][j] + (nd[v] == s[i])*(dp1[u][i+][j]))%M;
}
if(dp1[v][i][j] < )
dp1[v][i][j] += M;
}
u =v;
}
vis[u] = true;
REP(i, g[u].size()) {
int v = g[u][i];
if(v == fa)
continue;
tarjan(v, u);
pa[v] = u;
}
REP(i, que[u].size()) {
int v = que[u][i].first;
int id = que[u][i].second;
if(!vis[v])
continue;
lca[id] = findset(v);
}
}
void solve() {
REP(ii, m) {
int w = lca[ii];
int u = qq[ii].first;
int v = qq[ii].second;
if(u == v) {
printf("%d\n", len == && s[] == nd[u]);
continue;
}
SET(t1, );
SET(t2, );
t1[] = t2[len+] = ;
if(w != u) {
Rep(i, , len+) {
int tmp = ;
Rep(x, , i+) {
tmp = (tmp + ((LL)t1[x-]*dp1[w][x][i])%M)%M;
}
t1[i] = (dp1[u][][i]-tmp)%M;
if(t1[i] < )
t1[i] += M;
}
}
if(w != v) {
VREP(i, len, ) {
int tmp = ;
VREP(x, len, i) {
tmp = (tmp + ((LL)t2[x+]*dp2[w][x][i])%M)%M;
}
t2[i] = (dp2[v][len][i] - tmp)%M;
if(t2[i] < )
t2[i] += M;
}
}
int ans = ;
REP(i, len+) {
if(s[i] == nd[w])
ans = (ans + ((LL)t1[i-]*t2[i+])%M)%M;
ans = (ans + ((LL)t1[i]*t2[i+])%M)%M;
if(ans < )
ans += M;
}
if(ans < )
ans += M;
printf("%d\n", ans);
}
}
int main() { int T;
for(int t = scanf("%d", &T); t <= T; t++) {
scanf("%d%d", &n, &m);
init(n);
REP(i, n-) {
int u, v;
scanf("%d%d", &u, &v);
g[u].pb(v);
g[v].pb(u);
}
s[] = '\0';
scanf("%s%s", nd+, s+);
len = strlen(s+);
REP(i, m) {
int u, v;
scanf("%d%d", &u, &v);
qq.pb(mp(u, v));
que[u].pb(mp(v, i));
que[v].pb(mp(u, i));
}
tarjan(, );
solve();
}
return ;
}

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. js中 this篇

    以下文案皆来自<你不知道的JavaScript 上卷>——读书笔记摘要 this 到底是什么? 排除了一些错误理解之后,我们来看看 this 到底是一种什么样的机制. 之前我们说过 thi ...

  2. php Composer中国全量镜像

    http://pkg.phpcomposer.com/ http://www.yiichina.com/doc/guide/2.0/intro-upgrade-from-v1 https://getc ...

  3. Xcode中添加代码块的方式

    在写代码的过程中,经常会有重复的代码(比如说,cell的使用),当然了复制粘贴也不是不行,但是Xcode提供了一个很方便的东西. 1.在Xcode右下角你会看到有一个{}的东西,这里是一些常用的代码块 ...

  4. Bootstrap使用心得

    久闻Twitter的Bootstrap框架强大且易用,近日为改版小丸工具箱的官网特地花了一周实践. 这篇文章总结我在使用Bootstarp中的一些关键点. 1.布局 Bootstrap框架的布局采用了 ...

  5. 层叠上下文 Stacking Context

    层叠上下文 Stacking Context 在CSS2.1规范中,每个盒模型的位置是三维的,分别是平面画布上的x轴,y轴以及表示层叠的z轴.对于每个html元素,都可以通过设置z-index属性来设 ...

  6. ES6的promise的学习

    1.Promise的含义: Promise是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大.它由社区最早提出和实现,ES6将其写进了语言标准,统一了用法,原生提供了Pro ...

  7. 暑假集训(2)第七弹 -----今年暑假不AC(hdu2037)

    J - 今年暑假不AC Crawling in process... Crawling failed Time Limit:1000MS     Memory Limit:32768KB     64 ...

  8. java.lang.StringBuilder源码分析

    StringBuilder是一个可变序列的字符数组对象,它继承自AbstractStringBuilder抽象类.它不保证同步,设计出来的目的是当这个字符串缓存只有单线程使用的时候,取代StringB ...

  9. 事件兼容IE

    addEvent:function(target, functionref, tasktype) { if (target.addEventListener) target.addEventListe ...

  10. PHP权限分配思路

    常见四种方式1.用户+组+角色+权限2.用户+组+权限3.用户+角色+权限(最多用)4.用户+权限以第三种为例:权限:用户操作的具体事件:如curd角色:指一类用户拥有的权限,如超级管理员,管理员,普 ...