CF375D Tree and Queries

题目

luogu

思路

唯有水题暖人心
只用子树的树,当然dfs序列
区间查询出现k次的数字的个数
nub[i]记录出现次数大于i的数字个数
发现只是O(1)的转移,想想就OK了

代码

ps:为了更好地阅读,我加一段cpp吧

void add(int x)
{   
    hav[x]++;
    nub[hav[x]]++;
}
void delet(int x)
{
    nub[hav[x]]--;
    hav[x]--;
}
FOR(i,1,m)
{
    while(l > Q[i].s) add(a[b[--l]]);
    while(l < Q[i].s) delet(a[b[l++]]);
    while(r < Q[i].t) add(a[b[++r]]);
    while(r > Q[i].t) delet(a[b[r--]]);
    Q[i].ans=nub[Q[i].k];
}
#include <bits/stdc++.h>
#define FOR(i,a,b) for(int i=a;i<=b;++i)
using namespace std;
const int maxn=1e5+7;
int n,m,a[maxn],b[maxn],begg[maxn],endd[maxn],js,nub[maxn],hav[maxn];;
int head[maxn<<1],tot,belong[maxn];
struct node
{
    int s,t,k,id,ans;
}Q[maxn];
bool cmp1(const node &a,const node &b){ return belong[a.s]==belong[b.s] ? a.t<b.t : a.s<b.s;}
bool cmp2(const node &a,const node &b){ return a.id<b.id;}
struct edge
{
    int v,nxt;
}e[maxn<<1];
void add_edge(int u,int v)
{
    e[++tot].v=v;
    e[tot].nxt=head[u];
    head[u]=tot;
}
int read()
{
    int x=0,f=1;char s=getchar();
    for(;s<'0'||s>'9';s=getchar()) if(s=='-') f=-1;
    for(;s>='0'&&s<='9';s=getchar()) x=x*10+s-'0';
    return x*f;
}
void dfs(int u,int f)
{
    b[++js]=u;
    begg[u]=js;
    for(int i=head[u];i;i=e[i].nxt)
    {
        int v=e[i].v;
        if(v==f) continue;
        dfs(v,u);
    }
    endd[u]=js;
}
int main()
{
    n=read(),m=read();
    int k=sqrt(n);
    FOR(i,1,n) a[i]=read();
    FOR(i,1,n) belong[i]=(i-1)/k+1;
    FOR(i,1,n-1)
    {
        int x=read(),y=read();
        add_edge(x,y);
        add_edge(y,x);
    }
    dfs(1,0);
    FOR(i,1,m)
    {
        int x=read(),y=read();
        Q[i].s=begg[x];
        Q[i].t=endd[x];
        Q[i].k=y;
        Q[i].id=i;
    }
    sort(Q+1,Q+1+m,cmp1);
    int l=1,r=0;
    FOR(i,1,m)
    {
        while(l > Q[i].s) hav[a[b[--l]]]++,nub[hav[a[b[l]]]]++;
        while(l < Q[i].s) nub[hav[a[b[l]]]]--,hav[a[b[l++]]]--;
        while(r < Q[i].t) hav[a[b[++r]]]++,nub[hav[a[b[r]]]]++;
        while(r > Q[i].t) nub[hav[a[b[r]]]]--,hav[a[b[r--]]]--;
        Q[i].ans=nub[Q[i].k];
    }
    sort(Q+1,Q+1+m,cmp2);
    FOR(i,1,m) printf("%d\n",Q[i].ans);
}

猜你喜欢

转载自www.cnblogs.com/lovedsr/p/9812875.html