《洛谷CF570D Tree Requests》
挺好的一道题:
首先,可以dsu on tree做。
这里的精髓就是当奇数个数的点 <= 1时,就能构成。(这里对2取模了。)
那么可以用异或操作来实现对二取模。同时异或两次也就相当于没有做异或操作。
所以也可以用异或来清空轻儿子的贡献。
那么就需要状压每个字母的状态。因为只有26个字母。
这里还有个问题,就是查询要怎么办。
我们可以把查询挂到点上,然后统计完后,去查询每个操作。
// Author: levil #include<bits/stdc++.h> using namespace std; typedef long long LL; typedef pair<LL,int> pii; const int N = 5e5+5; const int M = 1e5+5; const LL Mod = 199999; #define rg register #define pi acos(-1) #define INF 1e9 #define CT0 cin.tie(0),cout.tie(0) #define IO ios::sync_with_stdio(false) #define dbg(ax) cout << "now this num is " << ax << endl; namespace FASTIO{ inline LL read(){ LL x = 0,f = 1;char c = getchar(); while(c < '0' || c > '9'){if(c == '-') f = -1;c = getchar();} while(c >= '0' && c <= '9'){x = (x<<1)+(x<<3)+(c^48);c = getchar();} return x*f; } void print(int x){ if(x < 0){x = -x;putchar('-');} if(x > 9) print(x/10); putchar(x%10+'0'); } } using namespace FASTIO; void FRE(){/*freopen("data1.in","r",stdin); freopen("data1.out","w",stdout);*/} int n,m,val[N],ssize[N],son[N],Son,dep[N],ans[N]; int cnt[N]; struct Query{int id,d;}; vector<Query> vec[N]; vector<int> G[N]; char s[N]; void dfs(int u,int fa) { ssize[u] = 1,dep[u] = dep[fa]+1; for(auto v : G[u]) { if(v == fa) continue; dfs(v,u); ssize[u] += ssize[v]; if(ssize[v] > ssize[son[u]]) son[u] = v; } } void slove(int u,int fa) { cnt[dep[u]] ^= (1<<val[u]); for(auto v : G[u]) { if(v == fa || v == Son) continue; slove(v,u); } } int check(int d) { int sum = 0; for(rg int i = 0;i < 26;++i) sum += ((cnt[d]>>i)&1); return sum; } void dfs1(int u,int fa,int opt) { for(auto v : G[u]) { if(v == fa || v == son[u]) continue; dfs1(v,u,0); } if(son[u]) dfs1(son[u],u,1),Son = son[u]; slove(u,fa); Son = 0; for(auto t : vec[u]) { ans[t.id] = check(t.d); } if(opt == 0) slove(u,fa); } int main() { n = read(),m = read(); for(rg int i = 2;i <= n;++i) { int par;par = read(); G[i].push_back(par); G[par].push_back(i); } dfs(1,0); scanf("%s",s); int len = strlen(s); for(rg int i = 0;i < len;++i) val[i+1] = s[i]-'a'; for(rg int i = 1;i <= m;++i) { int v,h;v = read(),h = read(); vec[v].push_back(Query{i,h}); } dfs1(1,0,0); for(rg int i = 1;i <= m;++i) printf("%s\n",ans[i] <= 1 ? "Yes" : "No"); // system("pause"); }
同时,这里的话也可以用线段树合并来解决。
我们对每个点的开n个位置来记录每个点的深度状压的值。
然后线段树动态开点去合并即可。
那么查询的时候就是个单点查询某个深度的状压值了。
注意合并到边界要特判。这里debug了半天.
// Author: levil #include<bits/stdc++.h> using namespace std; typedef long long LL; typedef pair<LL,int> pii; const int N = 5e5+5; const int M = 1e5+5; const LL Mod = 199999; #define rg register #define pi acos(-1) #define INF 1e9 #define CT0 cin.tie(0),cout.tie(0) #define IO ios::sync_with_stdio(false) #define dbg(ax) cout << "now this num is " << ax << endl; namespace FASTIO{ inline LL read(){ LL x = 0,f = 1;char c = getchar(); while(c < '0' || c > '9'){if(c == '-') f = -1;c = getchar();} while(c >= '0' && c <= '9'){x = (x<<1)+(x<<3)+(c^48);c = getchar();} return x*f; } void print(int x){ if(x < 0){x = -x;putchar('-');} if(x > 9) print(x/10); putchar(x%10+'0'); } } using namespace FASTIO; void FRE(){/*freopen("data1.in","r",stdin); freopen("data1.out","w",stdout);*/} int n,m,rt[N],top = 0,val[N],dep[N],ans[N]; struct Node{int L,r,val;}node[N*20]; struct Query{int id,d;}; vector<int> G[N]; vector<Query> vec[N]; char s[N]; int build(int L,int r,int x,int tmp) { int idx = ++top; if(L == r) { node[idx].val ^= (1<<tmp); return idx; } int mid = (L+r)>>1; if(mid >= x) node[idx].L = build(L,mid,x,tmp); else node[idx].r = build(mid+1,r,x,tmp); node[idx].val = node[node[idx].L].val ^ node[node[idx].r].val; return idx; } int Merge(int x,int y,int L,int r) { if(x == 0) return y; if(y == 0) return x; if(L == r) { node[x].val ^= node[y].val; return x; } int mid = (L+r)>>1; node[x].L = Merge(node[x].L,node[y].L,L,mid); node[x].r = Merge(node[x].r,node[y].r,mid+1,r); if(L == r) node[x].val = node[x].val ^ node[y].val; node[x].val = node[node[x].L].val ^ node[node[x].r].val; return x; } int query(int x,int L,int r,int idx) { if(L == r) return node[idx].val; int mid = (L+r)>>1; if(mid >= x) return query(x,L,mid,node[idx].L); else return query(x,mid+1,r,node[idx].r); } void dfs(int u,int fa) { dep[u] = dep[fa]+1; for(auto v : G[u]) if(v != fa) dfs(v,u); } int check(int x) { int sum = 0; for(rg int i = 0;i < 26;++i) sum += ((x>>i)&1); return sum; } void dfs1(int u,int fa) { for(auto v : G[u]) { if(v == fa) continue; dfs1(v,u); rt[u] = Merge(rt[u],rt[v],1,n); } for(auto t : vec[u]) ans[t.id] = check(query(t.d,1,n,rt[u])); } int main() { n = read(),m = read(); for(rg int i = 2;i <= n;++i) { int par;par = read(); G[par].push_back(i); G[i].push_back(par); } dfs(1,0); scanf("%s",s); int len = strlen(s); for(rg int i = 0;i < len;++i) val[i+1] = s[i]-'a'; for(rg int i = 1;i <= n;++i) rt[i] = build(1,n,dep[i],val[i]); for(rg int i = 1;i <= m;++i) { int v,h;v = read(),h = read(); vec[v].push_back(Query{i,h}); } dfs1(1,0); for(rg int i = 1;i <= m;++i) printf("%s\n",ans[i] <= 1 ? "Yes" : "No"); system("pause"); }