hdu 4601 Letter Tree 2013多校1-2

不容易啊。。一个小错误让我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 2013多校1-2,布布扣,bubuko.com

时间: 2024-08-09 13:00:52

hdu 4601 Letter Tree 2013多校1-2的相关文章

hdu 4603 Color the Tree 2013多校1-4

这道题细节真的很多 首先可以想到a和b的最优策略一定是沿着a和b在树上的链走,走到某个点停止,然后再依次占领和这个点邻接的边 所以,解决这道题的步骤如下: 预处理阶段: step 1:取任意一个点为根节点,找出父子关系并且对这个树进行dp,求出从某个节点出发往下所包含的所有边的权值总和  复杂度O(n) step 2:从tree dp 的结果中计算对于某个节点,从某条边出发所包含的边的综合,并且对其从大到小进行排序 复杂度O(n*logn) step 3:dfs求出这颗树的欧拉回路,以及每个点的

【HDOJ】4601 Letter Tree

挺有意思的一道题,思路肯定是将图转化为Trie树,这样可以求得字典序.然后,按照trie的层次求解.一直wa的原因在于将树转化为线性数据结构时要从原树遍历,从trie遍历就会wa.不同结点可能映射为trie上的同一结点,如1->2 (a) 1->3(a) 2->4(b), 这是trie的结构是RT->a->b.然而,从结点3不能找到权重为b的路径.用RMQ求满足边界的rank最大值,通过sa找到该最大值对应的trie上的根.从而求解. 1 /* 4601 */ 2 #incl

2014多校第六场 1005 || HDU 4925 Apple Tree

题目链接 题意 : 给你一块n×m的矩阵,每一个格子可以施肥或者是种苹果,种一颗苹果可以得到一个苹果,但是如果你在一个格子上施了肥,那么所有与该格子相邻(指上下左右)的有苹果树的地方最后得到的苹果是两倍,如果(i,j)有一颗苹果树,(i-1,j)与(i,j+1)施了肥,那么苹果应该是1的两倍2,2的两倍4,最后是4个苹果,问你怎么安排苹果和施肥的格子使最后得到的苹果最多. 思路 : 画了图就可以看出来,苹果和苹果,肥与肥之间不要相邻就好了,所有的苹果之间都有施肥,所有施肥的格子都被苹果隔开了才能

hdu 4929 Another Letter Tree(LCA+DP)

hdu 4929 Another Letter Tree(LCA+DP) 题意:有一棵树n个节点(n<=50000),树上每个节点上有一个字母.m个询问(m<=50000),每次询问一个(a,b),问a节点到b节点的点不重复路径组成的字符串中子序列为s0的情况有多少种,s0长度小于等于30(注意s0是已经给定的,而不是每次询问都会给出一个新的). 解法:一个很直观的想法,求出lca(设其为w)后,枚举x,求出a到w的路径上,能匹配s0的x长度前缀的情况有多少种,令其为c[x].再求出b到w的路

HDU 4864 Task(2014多校--贪心)

Task 比赛当时思路想的差不多,感觉能过的,该处理的也都处理到了,最后还是没过,可能是二分写错了吧-.- 大意:给你n个机器,m个要完成的任务,每个机器跟任务都有两个属性,机器是最大工作时间跟等级,任务是需要工作的时间跟等级.完成一个任务可以得到500*(工作时间)+2*(等级)的报酬.完成任务的条件是机器的工作时间满足任务的需要,等级要大于等于任务的等级,一个机器只能用一次,一个任务也只能用一个机器去完成.需要进行策略选择,使得完成更多的任务. 思路:开始想的就是贪心,也想到了贪心的时候时间

hdu 5379 Mahjong tree(树形dp)

题目链接:hdu 5379 Mahjong tree 树形dp,每个节点最多有2个子节点为一棵节点数大于1的子树的根节点,而且要么后代的节点值都大于,要么都小于本身(所以tson不为0是,要乘2).对于K个单一节点的子节点,种类数即为全排K!.当一个节点没有兄弟节点时,以这个节点为根结点的子树,根可以选择最大或者最小. #pragma comment(linker, "/STACK:102400000,102400000") #include <cstdio> #inclu

HDU 4925 Apple Tree(推理)

HDU 4925 Apple Tree 题目链接 题意:给一个m*n矩阵种树,每个位置可以选择种树或者施肥,如果种上去的位置就不能施肥,如果施肥则能让周围果树产量乘2,问最大收益 思路:推理得到肯定是果树和肥料交叉种好,类似国际象棋棋盘,黑的种,白的施肥,由于格子数不多,直接去枚举每个位置即可.如果题目格子数多的话,其实也可以推出公式一步得到答案 代码: #include <cstdio> #include <cstring> const int d[4][2] = {{0, 1}

HDU 4925 Apple Tree (瞎搞)

找到规律,各一个种一棵树,或者施肥.先施肥,先种树一样. Apple Tree Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others) Total Submission(s): 197    Accepted Submission(s): 135 Problem Description I've bought an orchard and decide to plant some

hdu 4925 Apple Tree

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4925 思路:直接计算坐标和,如果为奇数就种树,但要注意行或列为1的情况. 写啦两种代码:一种直接判断计算的,另一种优化计算的 code1: #include<cstdio> #include<iostream> #include<algorithm> #include<cmath> using namespace std; int main() { int T;