hdu 4601 Letter Tree
不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的更多相关文章
- 【HDOJ】4601 Letter Tree
挺有意思的一道题,思路肯定是将图转化为Trie树,这样可以求得字典序.然后,按照trie的层次求解.一直wa的原因在于将树转化为线性数据结构时要从原树遍历,从trie遍历就会wa.不同结点可能映射为t ...
- HDU 5513 Efficient Tree
HDU 5513 Efficient Tree 题意 给一个\(N \times M(N \le 800, M \le 7)\)矩形. 已知每个点\((i-1, j)\)和\((i,j-1)\)连边的 ...
- HDU 4925 Apple Tree(推理)
HDU 4925 Apple Tree 题目链接 题意:给一个m*n矩阵种树,每一个位置能够选择种树或者施肥,假设种上去的位置就不能施肥,假设施肥则能让周围果树产量乘2.问最大收益 思路:推理得到肯定 ...
- HDU 4871 Shortest-path tree 最短路 + 树分治
题意: 输入一个带权的无向连通图 定义以顶点\(u\)为根的最短路生成树为: 树上任何点\(v\)到\(u\)的距离都是原图最短的,如果有多条最短路,取字典序最小的那条. 然后询问生成树上恰好包含\( ...
- Hdu 5379 Mahjong tree (dfs + 组合数)
题目链接: Hdu 5379 Mahjong tree 题目描述: 给出一个有n个节点的树,以节点1为根节点.问在满足兄弟节点连续 以及 子树包含节点连续 的条件下,有多少种编号方案给树上的n个点编号 ...
- HDU 6035 - Colorful Tree | 2017 Multi-University Training Contest 1
/* HDU 6035 - Colorful Tree [ DFS,分块 ] 题意: n个节点的树,每个节点有一种颜色(1~n),一条路径的权值是这条路上不同的颜色的数量,问所有路径(n*(n-1)/ ...
- HDU 3333 - Turing Tree (树状数组+离线处理+哈希+贪心)
题意:给一个数组,每次查询输出区间内不重复数字的和. 这是3xian教主的题. 用前缀和的思想可以轻易求得区间的和,但是对于重复数字这点很难处理.在线很难下手,考虑离线处理. 将所有查询区间从右端点由 ...
- HDU 5573 Binary Tree 构造
Binary Tree 题目连接: http://acm.hdu.edu.cn/showproblem.php?pid=5573 Description The Old Frog King lives ...
- hdu 4786 Fibonacci Tree (2013ACMICPC 成都站 F)
http://acm.hdu.edu.cn/showproblem.php?pid=4786 Fibonacci Tree Time Limit: 4000/2000 MS (Java/Others) ...
随机推荐
- AC日记——Count on a tree II spoj
Count on a tree II 思路: 树上莫队: 先分块,然后,就好办了: 来,上代码: #include <cmath> #include <cstdio> #inc ...
- 洛谷——P1679 神奇的四次方数
P1679 神奇的四次方数 题目描述 在你的帮助下,v神终于帮同学找到了最合适的大学,接下来就要通知同学了.在班级里负责联络网的是dm同学,于是v神便找到了dm同学,可dm同学正在忙于研究一道有趣的数 ...
- What makes grep consider a file to be binary?
grep -a worked for me: $ grep --help [...] -a, --text equivalent to --binary-files=text
- [USACO09MAR]Cleaning Up
题目大意: 给你一个长度为n的序列a,你可以将其分为若干段,最终的答案为每一段不同数个数的平方和. 思路: 不难想到一个O(n^2)的DP: f[i]=min{f[j]+cnt(j,i)^2} 考虑一 ...
- 集合框架(04)HashMap
集合Map的简单方法:该集合存储键值对,一对一对往里面存,而且要保证健的唯一性 1.添加 put(K key,V value) putAll(Map<? Extends k, ? extends ...
- PHP的一些陷阱
1,空Array为False $a = array() if($a == false) { echo "This will be printed ! ! !" ; } 持续更新中
- 工作组模式下专用队列(Private Queue)如何引用远程队列路径
查了N久资料,包括MSDN的官方文档,对于同一工作组下,不同机器之间如何利用Private Queue(专用队列)来发送/接收消息,关于Path的引用一说,无非都是MachineName\privat ...
- Matlab绘图时横坐标重叠怎么办
如横坐标重叠了,咋回事?蛋疼. 后来发现plot里已经横坐标1到50了,我又写了个 set(gca,'XTick',1:1:50);没写XTickLabel,后来我把XTick注视了就好了.
- hdu4001
参考博客http://www.cppblog.com/aswmtjdsj/archive/2011/09/04/155049.aspx 维护4根双扫描线,左右和上下.暴力枚举,复杂度O(n^2). # ...
- Windows下cwRsyncServer双机连续同步部署
下载cwRsyncServer服务器端与客户端的安装文件:服务端下载:cwRsyncServer_4.0.5_Installer.zip客户端下载:cwRsync_4.0.5_Installer.zi ...