codeforces-375D-树上莫队

来源:互联网 发布:数控线切割编程软件 编辑:程序博客网 时间:2024/06/09 18:31

题目大意:给定一棵有根树,每次询问一个节点的子树中颜色数大于等于k的颜色总数;

题目解析:搞出dfs序,其实就变成序列了,莫队也很好写,开个cnt数组记录颜色种数,再开个least数组记录至少i个的颜色个数;

AC代码:

#include<iostream>#include<cstdio>#include<algorithm>#include<cstring>#include<string>#include<cmath>using namespace std;const int maxn = 1e5+10;int pos[maxn];int col[maxn],c[maxn];int in[maxn],out[maxn];int n,m;struct edge{int to,next;}e[maxn<<1];int head[maxn],tot;void addedge(int u,int v){e[tot].to=v;e[tot].next=head[u];head[u]=tot++;}struct Query{    int l,r,id,ans,k;    friend bool operator < (const Query &R, const Query &T)    {        return pos[R.l]<pos[T.l] || (pos[R.l]==pos[T.l] && R.r<T.r);    }}Q[200010];bool cmp_id(const Query &a,const Query &b){    return a.id<b.id;}void dfs(int u,int fa){in[u]=++tot;c[tot]=col[u];for(int i=head[u];~i;i=e[i].next){int v=e[i].to;if(v==fa)continue;dfs(v,u);}out[u]=tot;}int cnt[maxn],least[maxn];void modify(int pos,int val){if(val==1){cnt[c[pos]]++;least[cnt[c[pos]]]++;}else {least[cnt[c[pos]]]--;cnt[c[pos]]--;}}void init(){tot=0;memset(head,-1,sizeof(head));memset(cnt,0,sizeof(cnt));memset(least,0,sizeof(least));scanf("%d%d",&n,&m);for(int i=1;i<=n;i++)scanf("%d",&col[i]);for(int i=1;i<n;i++){int u,v;scanf("%d%d",&u,&v);addedge(u,v);addedge(v,u);}tot=0;dfs(1,0);int limit=(int)sqrt((double)n+0.5);    for(int i=1;i<=n;++i)        pos[i]=(i-1)/limit+1;    for(int i=1;i<=m;i++) {   int x,y;   scanf("%d%d",&x,&y);    Q[i].l=in[x]; Q[i].r=out[x]; Q[i].id=i; Q[i].k=y;    }    sort(Q+1,Q+m+1);}void solve(){for(int i=Q[1].l;i<=Q[1].r;i++){cnt[c[i]]++;least[cnt[c[i]]]++;}Q[1].ans=least[Q[1].k];int l=Q[1].l,r=Q[1].r;    for(int i=2;i<=m;++i)    {        if(r<Q[i].r)        {            for(r=r+1;r<Q[i].r;++r)                modify(r,1);            modify(r,1);        }        if(Q[i].l<l)        {            for(l=l-1;Q[i].l<l;--l)                modify(l,1);            modify(l,1);        }        if(Q[i].r<r)            for(;Q[i].r<r;--r)                modify(r,-1);        if(l<Q[i].l)            for(;l<Q[i].l;++l)                modify(l,-1);        Q[i].ans=least[Q[i].k];    }    sort(Q+1,Q+m+1,cmp_id);    for(int i=1;i<=m;++i)        printf("%d\n",Q[i].ans);}int main(){    init();    solve();    return 0;}