Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #define _CRT_SECURE_NO_WARNINGS
- #include <bits/stdc++.h>
- #define boAshraf { ios_base::sync_with_stdio(false); cin.tie(NULL); }
- #define ll long long
- #define sz(s) (int)(s).size()
- #define endl "\n"
- #define ordered_set tree<ll, null_type, less_equal<ll>, rb_tree_tag, tree_order_statistics_node_update>
- #include <ext/pb_ds/assoc_container.hpp>
- #include <ext/pb_ds/tree_policy.hpp>
- using namespace __gnu_pbds;
- using namespace std;
- const int N = 2e5 + 5, mod1 = 1e9 + 7, p1 = 29, mod2 = 1e9 + 9, p2 = 31;
- const int LOG = 25;
- int pw1[N], inverse1[N];
- int pw2[N], inverse2[N];
- vector<vector<int>> pref1, pref2;
- vector<int> adj[N];
- char ch[N];
- int up[N][LOG], in[N], out[N], depth[N], timer;
- int add(int a, int b, int mod) {
- return (0LL + a + b + mod) % mod;
- }
- int mul(int a, int b, int mod) {
- return (1LL * a * b) % mod;
- }
- int FP(int b, int p, int mod) {
- if (!p) return 1;
- int ans = FP(b, p >> 1, mod);
- ans = mul(ans, ans, mod);
- if (p & 1) ans = mul(ans, b, mod);
- return ans;
- }
- void pre() {
- pw1[0] = inverse1[0] = 1;
- pw2[0] = inverse2[0] = 1;
- for (int i = 1; i < N; ++i) {
- pw1[i] = mul(pw1[i - 1], p1, mod1);
- inverse1[i] = FP(pw1[i], mod1 - 2, mod1);
- pw2[i] = mul(pw2[i - 1], p2, mod2);
- inverse2[i] = FP(pw2[i], mod2 - 2, mod2);
- }
- }
- void pref_calc(const string &s) {
- int n = sz(s);
- pair<int, int> val = {0, 0};
- for (int i = 0; i < n; ++i) {
- val.first = add(val.first, mul(s[i] - 'a' + 1, pw1[i], mod1), mod1);
- pref1.back().push_back(val.first);
- val.second = add(val.second, mul(s[i] - 'a' + 1, pw2[i], mod2), mod2);
- pref2.back().push_back(val.second);
- }
- }
- pair<int, int> calc(int l, int r, int idx) {
- if (l == 0) return {pref1[idx][r], pref2[idx][r]};
- int x = mul(add(pref1[idx][r], -pref1[idx][l - 1], mod1), inverse1[l], mod1);
- int y = mul(add(pref2[idx][r], -pref2[idx][l - 1], mod2), inverse2[l], mod2);
- return {x, y};
- }
- bool palin(int idx, int l, int r) {
- int add = sz(pref1) / 2;
- int l2=sz(pref1[idx])-1-r;
- int r2=sz(pref1[idx])-1-l;
- return calc(l, r, idx) == calc(l2, r2, idx + add);
- }
- void dfs(int u, int p) {
- in[u] = timer++;
- up[u][0] = p;
- for (int i = 1; i < LOG; ++i) {
- if (up[u][i - 1] != -1)
- up[u][i] = up[up[u][i - 1]][i - 1];
- else
- up[u][i] = -1;
- }
- for (auto v: adj[u]) {
- if (v != p) {
- depth[v] = depth[u] + 1;
- dfs(v, u);
- }
- }
- out[u] = timer++;
- }
- int ancestor(int node, int l) {
- for (int i = 0; i < LOG; ++i) {
- if (l & (1 << i)) {
- node = up[node][i];
- if (node == -1) return -1;
- }
- }
- return node;
- }
- int bs1(int root, vector<int> &v) {
- int st = 0, ed = v.size() - 1, L = -1;
- while (st <= ed) {
- int mid = (st + ed) / 2;
- int curr_node = v[mid];
- if (in[curr_node] >= in[root] ) {
- L = mid;
- ed = mid - 1;
- } else st = mid + 1;
- }
- return L;
- }
- int bs2(int root, vector<int> &v) {
- int st = 0, ed = v.size() - 1, R = -1;
- while (st <= ed) {
- int mid = (st + ed) / 2;
- int curr_node = v[mid];
- if (out[curr_node] <= out[root]) {
- R = mid;
- st = mid + 1;
- } else ed = mid - 1;
- }
- return R;
- }
- void File();
- void sol();
- int main() {
- boAshraf
- File();
- int t = 1;
- cin >> t;
- pre();
- while (t--) {
- sol();
- }
- return 0;
- }
- void sol() {
- timer = 0;
- int n, q;
- cin >> n >> q;
- for (int i = 1; i <= n; ++i) {
- cin >> ch[i];
- }
- for (int i = 1; i <= n; ++i) {
- adj[i].clear();
- for (int j = 0; j < LOG; ++j) {
- up[i][j] = -1;
- }
- }
- for (int i = 2; i <= n; ++i) {
- int v;
- cin >> v;
- adj[v].push_back(i);
- }
- for (int i = 1; i <= n; ++i) {
- sort(adj[i].begin(), adj[i].end());
- }
- dfs(1, -1);
- vector<string> level;
- vector<vector<int>> level_nodes;
- queue<int> Q;
- Q.push(1);
- while (!Q.empty()) {
- string x = "";
- vector<int> temp;
- int ss = sz(Q);
- while (ss--) {
- int u = Q.front();
- Q.pop();
- x += ch[u];
- temp.push_back(u);
- for (auto v: adj[u]) {
- depth[v] = depth[u] + 1;
- Q.push(v);
- }
- }
- level.push_back(x);
- level_nodes.push_back(temp);
- }
- for (auto &it: level) {
- pref1.push_back(vector<int>());
- pref2.push_back(vector<int>());
- pref_calc(it);
- }
- for (auto &it: level) {
- reverse(it.begin(), it.end());
- pref1.push_back(vector<int>());
- pref2.push_back(vector<int>());
- pref_calc(it);
- }
- while (q--) {
- int node, l;
- cin >> node >> l;
- int root = ancestor(node, l);
- int L = bs1(root, level_nodes[depth[node]]);
- int R = bs2(root, level_nodes[depth[node]]);
- cout << (palin(depth[root] + l, L, R) ? "YES" : "NO") << endl;
- }
- pref1 = pref2 = vector<vector<int>>();
- }
- void File() {
- #ifndef ONLINE_JUDGE
- freopen("input.txt", "r", stdin);
- freopen("output.txt", "w", stdout);
- #endif
- }
Advertisement
Add Comment
Please, Sign In to add comment