HDU 4601

来源:互联网 发布:南风知我意txt下载 编辑:程序博客网 时间:2024/06/05 01:09

广搜确定各点深度, 并以此沿广搜顺序将点加入数组 Sequence,序列里的深度逐渐增加,先序遍历树并依次编号,确定每个点及其子树的的编号范围,在Sequence 中二分查找某一深度的点的左右边界(Sequence 中的点的编号在某一深度其实是逐渐增加的) RMQ 查询最值。至于字典序,则在 遍历树的时候模拟字典树插入,然后求出每个点实际字典序(从根节点到它本身所连成的这个字符串字典序)

#pragma comment(linker,"/STACK:102400000,102400000")#include <cstdio>#include <cstring>#include <algorithm>#include <queue>using namespace std;typedef long long LL;typedef pair<int, int> PII;const int maxn = 110000;const int mod = (int) (1e9 + 7);int tp[maxn], Log[30];struct Range_Query {PII r[19][maxn];int n, i, j, k;void make(int a[], int Seq[]) {for (i = 1; i <= n; ++i)r[0][i] = PII(a[i], Seq[i]);for (i = 0; i < 19; ++i) {k = Log[i];for (j = 1; j + k <= n; ++j) {r[i + 1][j] = max(r[i][j], r[i][j + k]);}}}PII query(int L, int R) {if (R == L)return r[0][L];k = tp[R - L];return max(r[k][L], r[k][R - Log[k]]);}} RMQ;//==========================================================struct node {int v, next, ch;node(int v = 0, int next = -1, int ch = 0) :v(v), next(next), ch(ch) {}} edge[maxn << 2];int head[maxn], e;LL Hash[maxn + 111], POW[maxn];int Sequence[maxn], cnt;int Ccnt;int lhs[maxn], rhs[maxn];int Left[maxn], Right[maxn];int dis[maxn];int order[maxn], N, M;int val[maxn];bool vis[maxn];int arr[maxn];int Depth[maxn];void add_edge(int u, int v, int ch) {edge[e] = node(v, head[u], ch);head[u] = e++;edge[e] = node(u, head[v], ch);head[v] = e++;}void bfs() {static int q[maxn], front, rear;memset(vis, false, sizeof(vis));memset(Left, 0x7f, sizeof(Left));memset(Right, -1, sizeof(Right));front = rear = 0;q[rear++] = 1;int i, u, v;Sequence[++cnt] = 1;vis[1] = true;dis[1] = 0;while (front < rear) {u = q[front++];for (i = head[u]; ~i; i = edge[i].next) {v = edge[i].v;if (vis[v])continue;dis[v] = dis[u] + 1;q[rear++] = v;Sequence[++cnt] = v;Left[dis[v]] = min(Left[dis[v]], cnt);Right[dis[v]] = max(Right[dis[v]], cnt);vis[v] = true;}}}void find_index(int u, int dep, int &L, int &R) {int low = Left[dis[u] + dep], high = Right[dis[u] + dep];int l, r, m;l = low, r = high;while (l <= r) {m = (l + r) >> 1;if (val[m] >= lhs[u])L = m, r = m - 1;elsel = m + 1;}l = low, r = high;while (l <= r) {m = (l + r) >> 1;if (val[m] <= rhs[u])R = m, l = m + 1;elser = m - 1;}}void dfs(int u, int pre = -1) {int i, v;order[u] = ++Ccnt;lhs[u] = Ccnt;LL h;Depth[u] = dis[u];h = Hash[u] * 26;if (h >= mod)h %= mod;for (i = head[u]; ~i; i = edge[i].next) {v = edge[i].v;if (v == pre)continue;Hash[v] = h + edge[i].ch;if (Hash[v] >= mod)Hash[v] %= mod;dfs(v, u);Depth[u] = max(Depth[u], Depth[v]);}rhs[u] = Ccnt;}//==========================================================int Rank[maxn];struct TrieTree {int rt, tot;int cnt;struct node {int next[26];int cnt;void init() {cnt = 0;memset(next, 0, sizeof(next));}} tb[maxn];void init() {rt = tot = cnt = 0;tb[rt].init();}void insert(char s[]) {int i, rt = 0, t;for (i = 0; s[i]; ++i) {t = s[i] - 'a';if (!tb[rt].next[t]) {tb[++tot].init();tb[rt].next[t] = tot;}rt = tb[rt].next[t];}}void dfs(int u, int rt, int ch, int pre = -1) {int i, v, t;//printf("u %d rt %d  tot %d %c\n", u, rt, tot, ch + 'a');for (i = head[u]; ~i; i = edge[i].next) {v = edge[i].v;if (v == pre)continue;t = edge[i].ch;if (!tb[rt].next[t]) {tb[++tot].init();tb[rt].next[t] = tot;}dfs(v, tb[rt].next[t], t, u);}}void CalRank(int rt, int pre = -1) {int i;//printf("rt %d\n", rt);tb[rt].cnt = cnt++;for (i = 0; i < 26; ++i) {if (tb[rt].next[i])CalRank(tb[rt].next[i], rt);}}void go(int u, int rt, int pre = -1) {int i, v, t;Rank[u] = tb[rt].cnt;for (i = head[u]; ~i; i = edge[i].next) {v = edge[i].v;if (v == pre)continue;t = edge[i].ch;go(v, tb[rt].next[t], u);}}} Trie;//==========================================================void debug(int u, int pre = -1) {int i, v;printf("u %d Rank %d\n", u, Rank[u]);for (i = head[u]; ~i; i = edge[i].next) {v = edge[i].v;if (v == pre)continue;debug(v, u);}}//=========================int main() {int i, j, u, v, dep;char s[14];POW[0] = 1;for (i = 1; i <= maxn; ++i) {POW[i] = POW[i - 1] * 26;if (POW[i] >= mod)POW[i] %= mod;}Log[0] = 1;for (i = 1; i < 20; ++i)Log[i] = Log[i - 1] << 1;tp[1] = 0;i = 0;for (j = 2; j < maxn; ++j) {if (Log[i + 1] < j)tp[j] = ++i;elsetp[j] = i;//printf("%d %d\n",j,tp[j]);}int T;scanf("%d", &T);while (T--) {scanf("%d", &N);Ccnt = e = cnt = 0;memset(head, -1, sizeof(head));for (i = 1; i < N; ++i) {scanf("%d%d%s", &u, &v, s);add_edge(u, v, s[0] - 'a');}Trie.init();Trie.dfs(1, 0, 0);Trie.CalRank(0);Trie.go(1, 0);bfs();dfs(1, 0);for (i = 1; i <= cnt; ++i)val[i] = order[Sequence[i]];for (i = 1; i <= cnt; ++i) {arr[i] = Rank[Sequence[i]];}int L, R;RMQ.n = cnt;RMQ.make(arr, Sequence);int delta;scanf("%d", &M);PII tmp;LL ans;while (M--) {scanf("%d%d", &u, &dep);if (dis[u] + dep > Depth[u]) {puts("IMPOSSIBLE");} else {find_index(u, dep, L, R);tmp = RMQ.query(L, R + 1);v = tmp.second;delta = dis[v] - dis[u];ans = Hash[v] - Hash[u] * POW[delta];ans = (ans % mod + mod) % mod;printf("%I64d\n", ans);}}}return 0;}/* 10 1 2 a 1 3 b 2 4 c 2 5 b 2 6 c 5 10 v 6 7 z 3 9 y 3 8 x 4 1 3 2 2 9 1 1 2 20 1 2 a 1 3 b 2 4 c 2 5 b 2 6 c 5 10 v 6 7 z 3 9 y 3 8 x 3 17 h 11 15 t 7 15 a 10 16 z 16 18 z 18 19 z 18 20 y 7 12 x 8 14 a 8 13 y 5 1 6 2 3 3 2 2 4 7 2 */