CF570D Tree Requests

Tree Requests

https://ac.nowcoder.com/acm/problem/111044

题意:
给定一个以1为根的n个节点的树,每个点上有一个字母(a-z),每个点的深度定义为该节点到1号节点路径上的点数.每次询问 a,b 查询以a为根的子树内深度为b的节点上的字母重新排列之后是否能构成回文串.
题解:
dfs序+状态压缩+二分查找
这个题用到了很多小技巧,比如说异或前缀和等等。
我们首先对他跑一边dfs序,记录下每个点的时间戳。
把每个层点入度的时间戳放在一起,因为结点到某层,也要保证这一层是他的孩子。
所以我们用这个时间戳来确定到底是这一层的哪一段。
用二分查找分别找入度结点和出度结点,从而确定范围。
字母一共只有26个,于是考虑状态压缩。再对每层开一个vector维护前缀状态。
再用异或前缀和的小方法,在O(1)的时间复杂度内确定字母的奇偶的个数。
如果奇数个数大于1,那么则输出No

/*Keep on going Never give up*/
//#pragma GCC optimize(3,"Ofast","inline")
#include<bits/stdc++.h>
//#define int long long

#define endl '\n'
#define Accepted 0
#define AK main()
#define I_can signed
using namespace std;
const int maxn =5e5+10;
const int MaxN = 0x3f3f3f3f;
const int MinN = 0xc0c0c00c;
typedef long long ll;
const int inf=0x3f3f3f3f;
const ll mod=1e9+7;

int n,m;
string s;
vector<int> edge[maxn];
int in[maxn],out[maxn];
int deep[maxn];
vector<int>arr[maxn],inn[maxn],b[maxn];

int cnt,maxdeep;
void dfs(int u,int fa){
    in[u]=++cnt;
    deep[u]=deep[fa]+1;
    maxdeep=max(maxdeep,deep[u]);
    arr[deep[u]].push_back(u);
    inn[deep[u]].push_back(in[u]);
    for(auto i:edge[u]){
        dfs(i,u);
    }
    out[u]=cnt;
}
inline int lowbit(int x){return x&(-x);}
int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
    cin>>n>>m;
    for(int i=2;i<=n;i++){
        int x;
        cin>>x;
        edge[x].push_back(i);
    }
    cin>>s;
    //cout<<"dddddd"<<endl;
    dfs(1,0);
    //cout<<"dddddd"<<endl;
    for(int i=1;i<=maxdeep;i++){
        int y=0;
        for(auto j:arr[i]){
            int x=s[j-1]-'a';
            y^=(1<<x);
            b[i].push_back(y);
        }
    }
    for(int i=0;i<m;i++){
        int x,y;
        cin>>x>>y;
        int l,r;
        l=lower_bound(inn[y].begin(),inn[y].end(),in[x])-inn[y].begin();
        r=upper_bound(inn[y].begin(),inn[y].end(),out[x])-inn[y].begin()-1;
        if(r<0){
            cout<<"Yes"<<endl;
            continue;
        }
        int z;
        if(l<1) z=b[y][r];
        else z=b[y][r]^b[y][l-1];
        z-=lowbit(z);
        if(!z) cout<<"Yes"<<endl;
        else cout<<"No"<<endl;
    }
    return 0;
}

题解 文章被收录于专栏

主要写一些题目的题解

全部评论

相关推荐

喜欢走神的孤勇者练习时长两年半:爱华,信华,等华,黑华
点赞 评论 收藏
分享
尊尼获获:闺蜜在哪?
点赞 评论 收藏
分享
3 收藏 评论
分享
牛客网
牛客企业服务