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) ...
随机推荐
- Ubuntu 搭建 ***
在Ubuntu下安装ss很简单.只需要依次执行下面3条命令: apt-get update apt-get install python-pip pip install shadowsocks pip ...
- 关于Android攻击面
先对android整个攻击面有一个体系化的认识,有助于理清思路, 对今后的学习有很大的帮助. 什么是攻击向量:从语言语法的角度来说,是一个动词,描述用来执行攻击的方法,描述了攻击者如何到达并接触任意给 ...
- kibana-metric
1. Visualize 新建图形 2. 选择图形类型 3. 选择索引 4. 设置metric参数 4.1 count 4.2 unique count 5. 保存图形
- luogu P1072 Hankson的趣味题
题目链接 luogu P1072 Hankson 的趣味题 题解 啊,还是noip的题好做 额,直接推式子就好了 \(gcd(x,a_0)=a_1=gcd(\frac{x}{a_1},\frac{a_ ...
- centos更改文件所属用户和用户组
使用命令为chown和chgrp 更改文件夹或者文件的所属用户 chown -R username dirname chown username filename 更改文件夹或者文件的所属用户组 ch ...
- 关于#include文件包含
1.对于函数头文件: #include <filename> 一般对于标准库文件以一个.h后缀结尾: 2.对于本地文件: #include "filename.h" 对 ...
- python 小技巧(glob,guid,序列化,压缩字符,有序字典,sorted函数,分片)
1.glob模块 glob模块是最简单的模块之一,内容非常少.用它可以查找符合特定规则的文件路径名.跟使用windows下的文件搜索差不多.查找文件只用到三个匹配符:”*”, “?”, “[]”.”* ...
- 【Hadoop】MR 切片机制 & MR全流程
1.概念 2.Split机制 3.MR Shuffle过程 4.MR中REDUCE与MAP写作过程 5.MR全貌
- 【Hadoop】Hadoop MR异常处理
1.代码示例 package com.ares.hadoop.mr.flowsort; import java.io.IOException; import org.apache.hadoop.con ...
- 【ecshop---新增包邮卡功能】
一:需求分析 项目组要求新增类似虚拟卡的包邮卡,用户获得包邮卡的方式包括后台发送和前台自助充值.包邮卡有使用期限.订单使用包邮卡免除邮费.可以和其他优惠活动同时进行! 二:开发功能点 后台:新增包邮卡 ...