Codeforces Round #316 (Div. 2) D. Tree Requests(dsu)

题目链接

题意:对于m次询问 求解以vi为根节点 深度为hi的的字母能不能组合成回文串。

思路:暴力dsu找一边 简直就是神技!

#include
#define ll long long int
using namespace std;
inline ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
inline ll lcm(ll a,ll b){return a/gcd(a,b)*b;}
int moth[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};
int dir[4][2]={1,0 ,0,1 ,-1,0 ,0,-1};
int dirs[8][2]={1,0 ,0,1 ,-1,0 ,0,-1, -1,-1 ,-1,1 ,1,-1 ,1,1};
const int inf=0x3f3f3f3f;
const int N=500007;
const ll mod=1e9+7;
struct node{
    int h,id; 
    bool f;
    friend bool operator < (node a,node b){
        return a.id<b.id;
    }
};
vector<int> G[N];
char val[N];
int dp[N],son[N],cnt[N][26];
int odd[N];
int de[N];
int po=0;
vector h[N];
node ans[N];
void dfs(int u,int fa,int deep){
    dp[u]=1;
    de[u]=deep;
    for(int i=0;i){
        int v=G[u][i];
        if(v==fa) continue;
        dfs(v,u,deep+1);
        dp[u]+=dp[v];
        if(dp[v]>dp[son[u]]) son[u]=v; //树剖 
    }
}
void add(int u,int fa,int w,int deep){
    cnt[deep][val[u]-'a']+=w;
    if(cnt[deep][val[u]-'a']&1) odd[deep]++;
    else odd[deep]--;
    for(int i=0;i){
        int v=G[u][i];
        if(v==fa||v==po) continue;
        add(v,u,w,deep+1);
    }
}
int num=0;
void dfss(int u,int fa,int opt,int deep){
    for(int i=0;i){
        int v=G[u][i];
        if(v==fa) continue;
        if(v!=son[u]) dfss(v,u,0,deep+1);
    }
    if(son[u]) dfss(son[u],u,1,deep+1),po=son[u];
    add(u,fa,1,deep);
    po=0;
    for(int i=0;i){
        node tmp=h[u][i];
        if(odd[tmp.h]>=2) tmp.f=0;
        ans[++num]=tmp;
    }
    if(!opt) add(u,fa,-1,deep);
}
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    int n,m; cin>>n>>m;
    for(int i=2;i<=n;i++){
        int fa; cin>>fa;
        G[fa].push_back(i);
    }
    for(int i=1;i<=n;i++){
        cin>>val[i];    
    }
    for(int i=1;i<=m;i++){
        int vi,hi; cin>>vi>>hi;
        node tmp; tmp.h=hi; tmp.f=1; tmp.id=i;
        h[vi].push_back(tmp);
    }
    dfs(1,0,1);
    dfss(1,0,1,1);
    sort(ans+1,ans+1+m);
    for(int i=1;i<=num;i++){
        if(ans[i].f) cout<<"Yes\n";
        else cout<<"No\n";
    }
    return 0;
}

 

转载于:https://www.cnblogs.com/wmj6/p/11128785.html

你可能感兴趣的:(Codeforces Round #316 (Div. 2) D. Tree Requests(dsu))