不easy啊。。

一个小错误让我wa死了。找了一个晚上,怎么都找不到

最后是对拍代码找到的错误。发现当步数比較小的时候答案就是对的,比較大的时候就不正确了

想到一定是什么地方越界了。。

power[i] = (i64)(power[i - 1] * 26) % mod;

就是这行。。

改成  power[i] = ((i64)power[i - 1] * 26) % mod;

就过了。。。

这道题总的来说就是很综合,什么方面都涉及一点,核心部分还是把树转化成序列之后二分边界+RMQ,用dfn来确定边界的这种方法很好,很有意思

事实上另一种方法,就是先从u节点往下走一步。然后在trie里面找,这个时候能够直接确定位置。由于在trie中已经是有序的了

两种都能够,第一种相对来说好实现一点

(hdu如今怎么不会爆栈了。

。)

//#pragma comment(linker, "/STACK:102400000,102400000")
#include<iostream>
#include<vector>
#include<algorithm>
#include<cstdio>
#include<queue>
#include<stack>
#include<string>
#include<map>
#include<set>
#include<cmath>
#include<cassert>
#include<cstring>
#include<iomanip>
using namespace std;
#ifdef _WIN32
typedef __int64 i64;
#define out64 "%I64d\n"
#define in64 "%I64d"
#else
typedef long long i64;
#define out64 "%lld\n"
#define in64 "%lld"
#endif
/************ for topcoder by zz1215 *******************/
#define foreach(c,itr) for(__typeof((c).begin()) itr=(c).begin();itr!=(c).end();itr++)
#define FOR(i,a,b) for( int i = (a) ; i <= (b) ; i ++)
#define FF(i,a) for( int i = 0 ; i < (a) ; i ++)
#define FFD(i,a,b) for( int i = (a) ; i >= (b) ; i --)
#define S64(a) scanf(in64,&a)
#define SS(a) scanf("%d",&a)
#define LL(a) ((a)<<1)
#define RR(a) (((a)<<1)+1)
#define pb push_back
#define pf push_front
#define X first
#define Y second
#define CL(Q) while(!Q.empty())Q.pop()
#define MM(name,what) memset(name,what,sizeof(name))
#define MC(a,b) memcpy(a,b,sizeof(b))
#define MAX(a,b) ((a)>(b)?(a):(b))
#define MIN(a,b) ((a)<(b)?(a):(b))
#define read freopen("out.txt","r",stdin)
#define write freopen("out1.txt","w",stdout) const int inf = 0x3f3f3f3f;
const i64 inf64 = 0x3f3f3f3f3f3f3f3fLL;
const double oo = 10e9;
const double eps = 10e-9;
const double pi = acos(-1.0);
const int mod = 1000000007;
const int maxn = 100111; struct Node
{
int now;
int to;
int c;
}; struct Trie
{
int to[26];
int rank;
}zx[maxn]; int head = 0;
int use; int get()
{
use++;
MM(zx[use].to, -1);
zx[use].rank = 0;
return use;
} int T;
int n, m;
vector<Node>g[maxn];
vector<int>level[maxn];
int dep[maxn];
int dfn[maxn];
int dfv[maxn];
int df; int power[maxn];
int vis[maxn];
int t[maxn]; int pos[maxn];
int pmod[maxn];
int rankmod[maxn];
int rk; int c[maxn]; int dfnpos[maxn];
int es[maxn][2];
vector<int>ary;
int st[maxn][20];
int pow2[20];
int lg2[maxn]; void dfs(int now=1,int step=0)
{
vis[now] = true;
int to;
dfn[now] = df;
dfv[df] = now;
df++;
dep[now] = step;
for (int i = 0; i <(int) g[now].size(); i++)
{
to = g[now][i].to;
if (!vis[to])
{
t[to] = now;
c[to] = g[now][i].c;
dfs(to,step+1);
}
}
} void make_trie()
{
use = -1;
get();
int trie = head;
int now = 1;
pos[now] = trie;
int to,temp;
pmod[0] = 0;
for (int i = 2; i < df; i++)
{
to = dfv[i];
now = t[to];
trie = pos[now];
if (zx[trie].to[c[to]] == -1)
{
temp = get();
zx[trie].to[c[to]] = temp;
pmod[temp] = ((i64)pmod[trie] * 26 + c[to]) % mod;
}
pos[to] = zx[trie].to[c[to]];
}
} void make_rank(int now = head)
{
zx[now].rank = rk++;
for (int i = 0; i < 26; i++)
{
if (zx[now].to[i] != -1)
{
make_rank(zx[now].to[i]);
}
}
} void sparsetable()
{
for (int i = 1; i <= n; i++)
{
st[i][0] = zx[pos[dfv[ary[i]]]].rank;
}
for (int j = 1; j <= lg2[n]; j++)
{
for (int i = 1; i <= n; i++)
{
if (i + pow2[j - 1] <= n)
{
st[i][j] = max(st[i][j - 1], st[i + pow2[j - 1]][j - 1]);
}
else
{
st[i][j] = st[i][j - 1];
}
}
}
} int rmq(int l,int r)
{
return max(st[l][lg2[r - l]], st[r - pow2[lg2[r - l]]][lg2[r - l]]);
} int find(int x, int step)
{
int low = dfn[x];
int up;
int temp = dfnpos[dfn[x]] + 1;
step += dep[x];
int l, r;
if (temp < es[dep[x]][1])
{
up = ary[temp];
}
else
{
up = inf;
}
l = upper_bound (ary.begin() + es[step][0], ary.begin() + es[step][1], low ) - ary.begin();
r = upper_bound (ary.begin() + es[step][0], ary.begin() + es[step][1], up ) - ary.begin();
if (l == r)
{
return -1;
}
int mrank = rmq(l, r);
int xrank = zx[pos[x]].rank;
return (((i64)rankmod[mrank] - ((i64)rankmod[xrank] * (i64)power[step - dep[x]])%mod)+mod)%mod;
} void start()
{
for (int i = 0; i <= n; i++)
{
vis[i] = false;
}
t[1] = -1;
df = 1;
dfs();
for (int i = 1; i <= n; i++)
{
level[dep[i]].push_back(dfn[i]);
}
for (int i = 1; i <= n; i++)
{
sort(level[i].begin(), level[i].end());
}
ary.clear();
ary.push_back(0);
for (int i = 0; i <= n; i++)
{
es[i][0] = ary.size();
for (int j = 0; j < (int)level[i].size(); j++)
{
ary.push_back(level[i][j]);
}
es[i][1] = ary.size();
} for (int i = 1; i <= n; i++)
{
dfnpos[ary[i]] = i;
} make_trie(); rk = 0;
make_rank(); for (int i = 0; i <= use; i++)
{
rankmod[zx[i].rank] = pmod[i];
} sparsetable(); } void destroy()
{
for (int i = 0; i <= n; i++)
{
g[i].clear();
level[i].clear();
}
} int main()
{
//read;
//write;
power[0] = 1;
for (int i = 1; i < maxn; i++)
{
power[i] = ((i64)power[i - 1] * 26) % mod;
}
pow2[0] = 1;
lg2[1] = 0;
for (int i = 1; i < 20; i++)
{
pow2[i] = pow2[i - 1] * 2;
if(pow2[i]<maxn)
lg2[pow2[i]] = i;
} for (int i = 3; i < maxn; i++)
{
if (!lg2[i])
{
lg2[i] = lg2[i - 1];
}
}
cin >> T;
while (T--)
{
cin >> n;
int x, y;
char z;
Node node;
for (int i = 1; i <= n - 1; i++)
{
//cin >> x >> y >> z;
scanf("%d%d %c", &x, &y, &z);
node.now = x;
node.to = y;
node.c = z - 'a';
g[node.now].push_back(node);
swap(node.now, node.to);
g[node.now].push_back(node);
}
start();
cin >> m;
for (int i = 1; i <= m; i++)
{
// cin >> x >> y;
scanf("%d%d", &x, &y);
if (y == 0)
{
printf("0\n");
continue;
}
int ans = find(x, y);
if (ans == -1)
{
// cout << "IMPOSSIBLE" << endl;
printf("IMPOSSIBLE\n");
}
else
{
// cout << ans << endl;
printf("%d\n",ans);
}
}
destroy();
}
return 0;
}

hdu 4601 Letter Tree的更多相关文章

  1. 【HDOJ】4601 Letter Tree

    挺有意思的一道题,思路肯定是将图转化为Trie树,这样可以求得字典序.然后,按照trie的层次求解.一直wa的原因在于将树转化为线性数据结构时要从原树遍历,从trie遍历就会wa.不同结点可能映射为t ...

  2. HDU 5513 Efficient Tree

    HDU 5513 Efficient Tree 题意 给一个\(N \times M(N \le 800, M \le 7)\)矩形. 已知每个点\((i-1, j)\)和\((i,j-1)\)连边的 ...

  3. HDU 4925 Apple Tree(推理)

    HDU 4925 Apple Tree 题目链接 题意:给一个m*n矩阵种树,每一个位置能够选择种树或者施肥,假设种上去的位置就不能施肥,假设施肥则能让周围果树产量乘2.问最大收益 思路:推理得到肯定 ...

  4. HDU 4871 Shortest-path tree 最短路 + 树分治

    题意: 输入一个带权的无向连通图 定义以顶点\(u\)为根的最短路生成树为: 树上任何点\(v\)到\(u\)的距离都是原图最短的,如果有多条最短路,取字典序最小的那条. 然后询问生成树上恰好包含\( ...

  5. Hdu 5379 Mahjong tree (dfs + 组合数)

    题目链接: Hdu 5379 Mahjong tree 题目描述: 给出一个有n个节点的树,以节点1为根节点.问在满足兄弟节点连续 以及 子树包含节点连续 的条件下,有多少种编号方案给树上的n个点编号 ...

  6. HDU 6035 - Colorful Tree | 2017 Multi-University Training Contest 1

    /* HDU 6035 - Colorful Tree [ DFS,分块 ] 题意: n个节点的树,每个节点有一种颜色(1~n),一条路径的权值是这条路上不同的颜色的数量,问所有路径(n*(n-1)/ ...

  7. HDU 3333 - Turing Tree (树状数组+离线处理+哈希+贪心)

    题意:给一个数组,每次查询输出区间内不重复数字的和. 这是3xian教主的题. 用前缀和的思想可以轻易求得区间的和,但是对于重复数字这点很难处理.在线很难下手,考虑离线处理. 将所有查询区间从右端点由 ...

  8. HDU 5573 Binary Tree 构造

    Binary Tree 题目连接: http://acm.hdu.edu.cn/showproblem.php?pid=5573 Description The Old Frog King lives ...

  9. hdu 4786 Fibonacci Tree (2013ACMICPC 成都站 F)

    http://acm.hdu.edu.cn/showproblem.php?pid=4786 Fibonacci Tree Time Limit: 4000/2000 MS (Java/Others) ...

随机推荐

  1. Ubuntu14.04 在右键中添加 在终端中打开

    1.在terminal中执行: sudo apt-get install nautilus-open-terminal 此时可能会提示:nable to locate package nautilus ...

  2. Python_Tips[2] -> 函数延后估值及字节码分析

    函数延后估值及字节码分析 在一个循环中定义了函数 f 但是并未对其进行调用,在循环结束后调用,此时i值为3故最终3个函数输出均为9.而非1, 4, 9. 这是由于在定义闭包函数 f 时,传入变量 i, ...

  3. 洛谷——P1595 信封问题

    P1595 信封问题 题目描述 某人写了n封信和n个信封,如果所有的信都装错了信封.求所有信都装错信封共有多少种不同情况. 输入输出格式 输入格式: 一个信封数n(n<=20) 输出格式: 一个 ...

  4. PDF审计工具peepdf

    PDF审计工具peepdf   PDF是Portable Document Format(便携式文档格式)的缩写.它是Adobe公司推出的文件格式规范.现在,PDF是网络电子书籍的主流格式.由于PDF ...

  5. Entity Framework贪婪加载筛选问题

    先说一下代码北京,现在有一个Table类,代表桌子,然后Tale里面级联这一系列订单Order,现在要获取这个Table中没有完成的订Order,用完include之后居然发现不知道该怎么写,上网找了 ...

  6. Bean装配--xml

    1,bean package com.songyan.zhangpei; import java.util.ArrayList; import com.sun.xml.internal.bind.v2 ...

  7. 集合框架(01)Collection

    1.集合:存储对象. 对象多了用集合存,数据多了用对象存 2.数组是固定长度,集合是不固定长度:数组是相同数据类型,集合是存储不同类型的对象 3 . 4.为什么会出现这么多的容器那,因为每一个容器对数 ...

  8. 50个最常用的UNIX/Linux命令

    转自http://get.jobdeer.com/493.get 1. tar command examples Create a new tar archive. $ tar cvf archive ...

  9. 彻底理解Javascript 中的 Promise(-------------------------------***---------------------------------)

    ES6原生提供了 Promise 对象. 到底是何方妖怪呢?打出来看看: 所谓 Promise,就是一个对象,用来传递异步操作的消息.它代表了某个未来才会知道结果的事件(通常是一个异步操作),并且这个 ...

  10. Eclipse常用小知识汇总

    原文:http://blog.csdn.net/jinzhencs/article/details/50462370 1.修改注释 自动出来的author