CF570D Tree Requests 樹上差分/dsu on tree
阿新 • • 發佈:2021-07-14
判斷能否構成迴文很簡單,出現次數為偶數的不用管,出現次數為奇數的最多有一個
可以用狀壓儲存出現次數的奇偶情況,判斷的時候 puts(ans[i]==(ans[i]&(-ans[i]))?"Yes":"No"); 這裡用到了樹狀陣列的lowbit求法
解法一:dsu on tree裸題詳情請見這裡
解法二:樹上差分
劃重點:能用這種方法是因為統計結果可撤銷,CF600E不能這麼做是因為求max不能撤銷
在進入一個子樹前後分別統計一下各個詢問的深度的狀壓
求法類似於字首和
#include<iostream> #include<cstdio> #include<vector> using namespace std; int n,m,tot,x,y; const int N=500010; int head[N],to[N],nt[N],ans[N],cnt[N]; char s[N]; struct ask{int id,dep;}; vector<int>v[N]; vector<ask>q[N]; void add(int f,int t) { to[++tot]=t;nt[tot]=head[f];head[f]=tot; } void dfs(int x,int dep) { for(int i=0,siz=q[x].size();i<siz;++i)v[x].push_back(cnt[q[x][i].dep]); cnt[dep]^=1<<(s[x]-'a'); for(int i=head[x];i;i=nt[i])dfs(to[i],dep+1); for(int i=0,siz=q[x].size();i<siz;++i)ans[q[x][i].id]=v[x][i]^cnt[q[x][i].dep]; } int main() { cin>>n>>m; for(int i=2;i<=n;++i) scanf("%d",&x),add(x,i); scanf("%s",s+1); for(int i=1;i<=m;++i) { scanf("%d%d",&x,&y); q[x].push_back((ask){i,y}); } dfs(1,1); for(int i=1;i<=m;++i)puts(ans[i]==(ans[i]&(-ans[i]))?"Yes":"No");//這裡是檢查ans[i]的二進位制中有幾個1 return 0; }