NC15323. 跳一跳,很简单的
描述
有一无限循环字母表:
现在有一棵n个节点(编号1-n)的有根树(1为根),树边边权为一个字母θ,在每一时刻θ会向前跳K步变为相应字母(即树边边权改变),如:
n每一时刻会向前跳3步,第1时刻变为q,第2时刻变为t,以此类推。
w每一时刻会向前跳2步,第1时刻变为y,第2时刻变为a,以此类推。
JK会给你Q个询问,让你判断两个节点在t时刻到根节点路径权值(路径权值为该节点到根节点的路径上字母按顺序拼成的字符串)的字典序大小关系。
输入描述
第一行一个整数T(0<T<3),代表测试数据组数。
每一组测试数据第一行给出树的节点数n(1<n<=100000)。
接下去的n-1行的第i行给出一个整数P(1<=P<=n),一个字母θ([a-z])以及字母变换的步数K(0<=K<=10000),表示编号为i+1的节点的父亲节点编号为P,以及边的描述。(输入保证为一棵树)
下一行询问数Q(0<Q<=10000),每个询问一行给出整数u(2<=u<=n),v(2<=v<=n),t(0<=t<=10000),判断编号为u,v两个节点在t时刻到根节点路径权值的字典序大小关系。
输出描述
对每个询问输出一行答案,
编号u到根节点路径权值的字典序小于v的输出“<”,
相等输出“=”,
否则输出“>”。(不包含该引号)
示例1
输入:
1 10 1 a 1 1 a 5 1 c 2 2 f 2 3 a 5 3 e 3 4 b 1 5 z 1 7 o 2 4 5 7 0 5 7 2 9 10 1 8 8 8
输出:
> < < =
C++14(g++5.4) 解法, 执行用时: 162ms, 内存消耗: 40036K, 提交时间: 2019-02-28 11:03:05
/* */ #include<cstdio> #include<algorithm> #include<cstring> #include<iostream> #include<queue> #include<cmath> #define ll long long #define M 100010 #define mmp make_pair using namespace std; const int base = 127; int read() { int nm = 0, f = 1; char c = getchar(); for(; !isdigit(c); c = getchar()) if(c == '-') f = -1; for(; isdigit(c); c = getchar()) nm = nm * 10 + c - '0'; return nm * f; } const int mod = 1000000007; ll poww[M]; char op[11]; int fa[M][18], b[M], a[M], n, deep[M]; ll hh[27][M]; vector<int> to[M]; void dfs(int now) { for(int i = 0; i < to[now].size(); i++) { int vj = to[now][i]; deep[vj] = deep[now] + 1; for(int i = 0, ch = a[vj]; i < 26; i++, (ch += b[vj])) { if(ch >= 26) ch -= 26; hh[i][vj] = (hh[i][now] * base + ch) % mod; } dfs(vj); } } int main() { poww[0] = 1; for(int i = 1; i < M; i++) poww[i] = poww[i - 1] * base % mod; int t = read(); while(t--) { n = read(); for(int i = 2; i <= n; i++) { fa[i][0] = read(); scanf("%s", op); b[i] = read(); to[fa[i][0]].push_back(i); a[i] = op[0] - 'a'; b[i] %= 26; } for(int i = 1; 1 << i <= n; i++) for(int j = 1; j <= n; j++) fa[j][i] = fa[fa[j][i - 1]][i - 1]; dfs(1); int q = read(); while(q--) { int vi = read(), vj = read(), v = read() % 26; for(int i = 17; i >= 0; i--) { if(min(deep[vi], deep[vj]) < (1 << i)) continue; ll ih = (hh[v][vi] - hh[v][fa[vi][i]] * poww[1 << i] % mod + mod) % mod; ll jh = (hh[v][vj] - hh[v][fa[vj][i]] * poww[1 << i] % mod + mod) % mod; if(ih == jh) vi = fa[vi][i], vj = fa[vj][i]; } int aa = (a[vi] + v * b[vi]) % 26, bb = (a[vj] + v * b[vj]) % 26; if(aa < bb) puts("<"); if(aa == bb) puts("="); if(aa > bb) puts(">"); } for(int i = 1; i <= n; i++) to[i].clear(); } return 0; } /* 2 10 1 a 1 1 a 5 1 c 2 2 f 2 3 a 5 3 e 3 4 b 1 5 z 1 7 o 2 4 5 7 0 5 7 2 9 10 1 8 8 8 10 1 a 1 1 a 5 1 c 2 2 f 2 3 a 5 3 e 3 4 b 1 5 z 1 7 o 2 4 5 7 0 5 7 2 9 10 1 8 8 8 */
C++11(clang++ 3.9) 解法, 执行用时: 211ms, 内存消耗: 13144K, 提交时间: 2019-02-02 15:28:56
#include<cstdio> #include<algorithm> #include<cstring> #include<vector> using namespace std; int gi(){ int x=0,w=1;char ch=getchar(); while((ch<'0'||ch>'9')&&ch!='-')ch=getchar(); if(ch=='-')w=0,ch=getchar(); while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+ch-'0',ch=getchar(); return w?x:-x; } #define ll unsigned long long const int N=1e5+5; const ll base=20020415; int T,n,q,nxt[N],head[N],ch[N],k[N],fa[N][18],u[N],v[N],ans[N]; ll pw[18],hsh[N];char sgn[]={'>','=','<'}; vector<int>id[26]; void dfs(int u){ for(int j=1;j<18;++j)fa[u][j]=fa[fa[u][j-1]][j-1]; for(int v=head[u];v;v=nxt[v])dfs(v); } void dfs(int u,int t){ for(int v=head[u];v;v=nxt[v]) hsh[v]=hsh[u]*base+(ch[v]+k[v]*t)%26+233,dfs(v,t); } ll cal(int u,int j){ return hsh[u]-hsh[fa[u][j]]*pw[j]; } int main(){ pw[0]=base; for(int i=1;i<18;++i)pw[i]=pw[i-1]*pw[i-1]; T=gi();while(T--){ n=gi();memset(head,0,sizeof(head)); for(int i=2,f;i<=n;++i){ fa[i][0]=f=gi();ch[i]=getchar()-'a';k[i]=gi()%26; nxt[i]=head[f];head[f]=i; } dfs(1);q=gi(); for(int i=0;i<26;++i)id[i].clear(); for(int i=1;i<=q;++i){ u[i]=gi();v[i]=gi(); id[gi()%26].push_back(i); } for(int t=0;t<26;++t){ dfs(1,t); for(int i:id[t]){ int x=u[i],y=v[i]; for(int j=17;~j;--j) if(cal(x,j)==cal(y,j)) x=fa[x][j],y=fa[y][j]; if(cal(x,0)==cal(y,0))ans[i]=1; else if(cal(x,0)<cal(y,0))ans[i]=2; else ans[i]=0; } } for(int i=1;i<=q;++i)putchar(sgn[ans[i]]),putchar('\n'); } return 0; }