HDOJ多校联合第六场

先一道一道题慢慢补上,

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 = 50000 + 10;
 27 const int maxm = 33;
 28 const int M = 10007 ;
 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+1) {
 48         que[i].clear();
 49         g[i].clear();
 50         vis[i] = false;
 51         REP(j, maxm) REP(k, maxm) {
 52             dp1[i][j][k] = 0, dp2[i][j][k] = 0;
 53             if(j > k)
 54                 dp1[i][j][k] = 1;
 55             if(j < k)
 56                 dp2[i][j][k] = 1;
 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, 1, len+1)
 66         if(s[i] == nd[u]) {
 67             dp1[u][i][i] = dp2[u][i][i] = 1;
 68         }
 69     } else {
 70         int v = u;
 71         u = fa;
 72         Rep(i, 1, len+1) Rep(j, 1, len+1) {
 73             if(i >= j) {
 74                 dp2[v][i][j] = (dp2[v][i][j] + dp2[u][i][j] + (nd[v] == s[i])*(dp2[u][i-1][j]))%M;
 75             }
 76             if(dp2[v][i][j] < 0)
 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+1][j]))%M;
 80             }
 81             if(dp1[v][i][j] < 0)
 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 == 1 && s[1] == nd[u]);
109             continue;
110         }
111         SET(t1, 0);
112         SET(t2, 0);
113         t1[0] = t2[len+1] = 1;
114         if(w != u) {
115             Rep(i, 1, len+1) {
116                 int tmp = 0;
117                 Rep(x, 1, i+1) {
118                     tmp = (tmp + ((LL)t1[x-1]*dp1[w][x][i])%M)%M;
119                 }
120                 t1[i] = (dp1[u][1][i]-tmp)%M;
121                 if(t1[i] < 0)
122                     t1[i] += M;
123             }
124         }
125         if(w != v) {
126             VREP(i, len, 1) {
127                 int tmp = 0;
128                 VREP(x, len, i) {
129                     tmp = (tmp + ((LL)t2[x+1]*dp2[w][x][i])%M)%M;
130                 }
131                 t2[i] = (dp2[v][len][i] - tmp)%M;
132                 if(t2[i] < 0)
133                     t2[i] += M;
134             }
135         }
136         int ans = 0;
137         REP(i, len+1) {
138             if(s[i] == nd[w])
139                 ans = (ans + ((LL)t1[i-1]*t2[i+1])%M)%M;
140             ans = (ans + ((LL)t1[i]*t2[i+1])%M)%M;
141             if(ans < 0)
142                 ans += M;
143         }
144         if(ans < 0)
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-1) {
156             int u, v;
157             scanf("%d%d", &u, &v);
158             g[u].pb(v);
159             g[v].pb(u);
160         }
161         s[0] = ‘\0‘;
162         scanf("%s%s", nd+1, s+1);
163         len = strlen(s+1);
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(1, 0);
172         solve();
173     }
174     return 0;
175 }

HDOJ多校联合第六场

时间: 2024-10-11 18:04:29

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

HDOJ多校联合第五场

1001 题意:求逆序对,然后交换k次相邻的两个数,使得剩下的逆序对最少. 分析:题目用到的结论是:数组中存在一对逆序对,那么可以通过交换相邻两个数使得逆序对减少1,交换k次,可以最多减少k个. 嘉定ai>aj,i < j,如果ai,aj相邻的,那么显然可以通过交换减少1:不相邻的情况, 考虑ak,k = j-1; #11:ak > aj,那么ak,aj构成逆序对,交换后逆序对减少1: #12:ak<=aj,那么ai,ak构成逆序对,问题转化为更小规模,可以通过同样的方法进一步分析

2014多校联合-第六场

最近这两场好无奈啊... 今天这场最后30分钟敲1001,压力倍增,虽然思路比较明确,但是代码打起来不怎么容易. 但是还是好在25分钟左右debug结束.提交wa,再提交,依然WA.......最后5分钟,还是没有AC掉. 一开始以为是精度问题,后来才sb的发现原来数组开小了. 在压力环境下保证代码的效率和质量真不是一件容易的事情.不过数组开小了,真是不可原谅. 1001:Map 题目相当于几条链表.把链表排成几行. 然后枚举每一列的状态会被操作多少次. 然后把和累加起来,然后直接除以状态总数.

HDOJ多校联合第四场

B题: C题:仅由'A','G','C','T',4个字母组成,给定一个字符串S,|S|<=15,给定一个整数m,以m为长度且仅含4种字母的字符串T,求LCS(S,T)为0,1,2,3....|S|,时相应字符串T的数目. 分析:dp+状态压缩 反正我不会这题,也是看了羊神的代码之后才明白这题的思路 下面说说我的理解吧: 由于|S|长度最大为15,所以用一个二进制编码表示是哪些位置上的字母构成LCS,并求相应的数目. dp[0][st],dp[1][st]记录的是相应字母构成LCS时,T可能的数

hdu5353||2015多校联合第六场1001 贪心

http://acm.hdu.edu.cn/showproblem.php?pid=5353 Problem Description There are n soda sitting around a round table. soda are numbered from 1 to n and i-th soda is adjacent to (i+1)-th soda, 1-st soda is adjacent to n-th soda. Each soda has some candies

HDU 5793 A Boring Question (费马小定理) ---2016杭电多校联合第六场

A Boring Question Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 156    Accepted Submission(s): 72 Problem Description There are an equation.∑0≤k1,k2,?km≤n∏1?j<m(kj+1kj)%1000000007=?We define t

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

A Simple Nim Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 79    Accepted Submission(s): 48 Problem Description Two players take turns picking candies from n heaps,the player who picks the las

hdu5336 多校联合第四场1010 模拟+bfs优先队列

http://acm.hdu.edu.cn/showproblem.php?pid=5336 Problem Description XYZ is playing an interesting game called "drops". It is played on a r?c grid. Each grid cell is either empty, or occupied by a waterdrop. Each waterdrop has a property "siz

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

http://acm.hdu.edu.cn/showproblem.php? pid=5379 Problem Description Little sun is an artist. Today he is playing mahjong alone. He suddenly feels that the tree in the yard doesn't look good. So he wants to decorate the tree.(The tree has n vertexs, i

hdu5360||多校联合第6场1008 贪心

http://acm.hdu.edu.cn/showproblem.php?pid=5360 Problem Description There are n soda conveniently labeled by 1,2,-,n. beta, their best friends, wants to invite some soda to go hiking. The i-th soda will go hiking if the total number of soda that go hi