《洛谷CF570D Tree Requests》
阿新 • • 發佈:2020-09-03
挺好的一道題:
首先,可以dsu on tree做。
這裡的精髓就是當奇數個數的點 <= 1時,就能構成。(這裡對2取模了。)
那麼可以用異或操作來實現對二取模。同時異或兩次也就相當於沒有做異或操作。
所以也可以用異或來清空輕兒子的貢獻。
那麼就需要狀壓每個字母的狀態。因為只有26個字母。
這裡還有個問題,就是查詢要怎麼辦。
我們可以把查詢掛到點上,然後統計完後,去查詢每個操作。
// Author: levil #include<bits/stdc++.h> using namespace std; typedef long long LL; typedef pair<LL,intView Code> 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"); }View Code