Codeforces 570D Tree Requests

来源:互联网 发布:电商销售数据分析报告 编辑:程序博客网 时间:2024/05/22 06:55

Codeforces 570D Tree Requests

dsu on tree

题意

给一棵树,每个节点有一个字母。一些查询Q(x,d),查询x及其子树中,与根节点距离为d的所有字母是否可以构成回文串。

思路

两种思路,dfs序+树状数组或dsu on tree。

dfs序+树状数组
我们可以跑一遍dfs序,这样子树在dfs序中连续。dfs时同时处理出距根所有距离的节点。然后离线询问,按深度排序,开26个树状数组。处理到每一层时将当前层所有节点加入对应字母的树状数组,然后对每个询问的x的dfs序区间进行查询。
复杂度O(nlog2n),cf跑了1400ms,空间102400kb。

dsu on tree
标准dsu on tree板子,每一个深度开个bitset记录字母出现情况,第一次dfs记录深度,第二次dfs更新对应深度的bitset,再做查询。
复杂度O(nlogn),cf跑了1000ms,空间59100kb。优秀啊~

代码

dfs序+树状数组

#include<bits\stdc++.h>#define M(a,b) memset(a,b,sizeof(a))#define lson l,mid,rt<<1#define rson mid+1,r,rt<<1|1using namespace std;const int MAXN=500007;typedef long long LL;struct Edge{    int to, ne;}e[MAXN];int head[MAXN], edgenum;int val[MAXN];char c[MAXN];int depth[MAXN];struct Query{    int id;    int u, dp;}q[MAXN];int res[MAXN];bool cmp(Query a, Query b){    return a.dp<b.dp;}int dfscount, in[MAXN], ou[MAXN];int bit[26][MAXN];vector<int> dp[MAXN];inline int lowbit(int i) { return i&(-i); }void change(int i,int pos, int v){    while(pos<MAXN)        bit[i][pos]+=v, pos+=lowbit(pos);}int query(int i, int pos){    int ans=0;    while(pos>0)        ans+=bit[i][pos], pos-=lowbit(pos);    return ans;}void dfs(int u, int fa){    in[u]=++dfscount;    if(fa==-1) depth[u]=1;    else depth[u]=depth[fa]+1;    dp[depth[u]].push_back(u);    for(int i=head[u];~i;i=e[i].ne)        dfs(e[i].to, u);    ou[u]=dfscount;}int main(){    int n;    while(scanf("%d", &n)==1)    {        int qam;scanf("%d", &qam);        M(head, -1);edgenum=dfscount=0;        for(int i=2;i<=n;i++)        {            int fa;scanf("%d", &fa);            e[edgenum].to=i, e[edgenum].ne=head[fa], head[fa]=edgenum++;        }        scanf("%s", c+1);        for(int i=1;i<=n;i++)            val[i]=c[i]-'a';        for(int i=1;i<=qam;i++)        {            int t1, t2;scanf("%d%d", &t1, &t2);            q[i].id=i;q[i].u=t1, q[i].dp=t2;        }        dfs(1, -1);        sort(q+1, q+qam+1, cmp);        int cnt=1;        for(int i=1;i<=n;i++)        {            for(int j : dp[i])            {                int c=val[j];                change(c, in[j], 1);            }            while(q[cnt].dp==i)            {                int x=in[q[cnt].u]-1, y=ou[q[cnt].u];                int tmp=0;                for(int k=0;k<26;k++)                {                    tmp+=((query(k, y)-query(k, x))%2);                }                res[q[cnt].id]=(tmp<=1);                cnt++;            }            for(int j : dp[i])            {                int c=val[j];                change(c, in[j], -1);            }        }        for(int i=1;i<=qam;i++)            if(res[i]) printf("Yes\n");            else printf("No\n");    }    //system("pause");    return 0;}

dsu on tree

#include<bits\stdc++.h>#define M(a,b) memset(a,b,sizeof(a))#define lson l,mid,rt<<1#define rson mid+1,r,rt<<1|1using namespace std;const int MAXN=500007;typedef long long LL;struct Edge{    int to, ne;}e[MAXN];int head[MAXN], edgenum;int val[MAXN];char c[MAXN];int depth[MAXN], sz[MAXN], hson[MAXN];void dfs(int u, int fa){    if(fa==-1) depth[u]=1;    else depth[u]=depth[fa]+1;    sz[u]=1;    for(int i=head[u];~i;i=e[i].ne)    {        int to=e[i].to;        dfs(to, u);        if(!hson[to]) hson[u]=to;        else if(sz[hson[u]]<sz[to]) hson[u]=to;        sz[u]+=sz[to];    }}struct Query{    int id;    int u, dp;    int ne;}q[MAXN];int qhead[MAXN], res[MAXN];int hs;bitset<26> cnt[MAXN];void suan(int u, int fa){    cnt[depth[u]].flip(val[u]);    for(int i=head[u];~i;i=e[i].ne)        if(e[i].to!=hs)            suan(e[i].to, fa);}void dfs(int u, int fa, int kep){    for(int i=head[u];~i;i=e[i].ne)        if(e[i].to!=hson[u])            dfs(e[i].to, u, 0);    if(hson[u]) dfs(hson[u], u, 1), hs=hson[u];    suan(u, fa);hs=0;    for(int i=qhead[u];~i;i=q[i].ne)    {        res[q[i].id]=(cnt[q[i].dp].count()<=1);    }    if(!kep) suan(u, fa);}int main(){    int n;    while(scanf("%d", &n)==1)    {        int qam;scanf("%d", &qam);        M(head, -1);edgenum=0;M(qhead, -1);        for(int i=2;i<=n;i++)        {            int fa;scanf("%d", &fa);            e[edgenum].to=i, e[edgenum].ne=head[fa], head[fa]=edgenum++;        }        scanf("%s", c+1);        for(int i=1;i<=n;i++)            val[i]=c[i]-'a';        for(int i=1;i<=qam;i++)        {            int t1, t2;scanf("%d%d", &t1, &t2);            q[i].id=i;q[i].u=t1, q[i].dp=t2, q[i].ne=qhead[t1];qhead[t1]=i;        }        dfs(1, -1);        dfs(1, -1, 0);        for(int i=1;i<=qam;i++)            if(res[i]) printf("Yes\n");            else printf("No\n");    }    //system("pause");    return 0;}
原创粉丝点击