[Codeforces375D]Tree and Queries(莫队+分块)

题目描述

传送门

题解

搞一个dfs序然后就变成了询问一坨区间
莫队
刚开始写了个bit结果tle
实际上写一个分块,维护块内和,然后 O(1) 修改 O(n) 查询就可以了
因为
ATP:修改次数非常多,能达到 nn ,但是查询次数不会超过 m

代码

#include
#include
#include
#include
#include
using namespace std;
#define N 200005
int n,m,x,y,dfs_clock,block,t;
int tot,point[N],nxt[N*2],v[N*2];
int in[N],out[N],pt[N],cnt[N],c[N],a[N],sum[N];
struct data{int k,l,r,id,ans;}q[N];
int L[N],R[N],num[N];

void add(int x,int y)
{
    ++tot; nxt[tot]=point[x]; point[x]=tot; v[tot]=y;
}
void dfs(int x,int fa)
{
    in[x]=++dfs_clock;pt[dfs_clock]=x;
    for (int i=point[x];i;i=nxt[i])
        if (v[i]!=fa)
            dfs(v[i],x);
    out[x]=dfs_clock;
}
int cmp(data a,data b)
{
    return num[a.l]int x,int val)
{
    sum[num[x]]-=a[x];
    a[x]+=val;
    sum[num[x]]+=a[x];
}
int query(int x)
{
    int ans=0;
    if (x>n) return ans;
    if (x==L[num[x]]) x=num[x];
    else
    {
        for (int i=x;i<=R[num[x]];++i) ans+=a[i];
        x=num[x]+1;
    }
    for (int i=x;i<=t;++i) ans+=sum[i];
    return ans;
}
void modui(int l,int r,int f)
{
    for (int i=l;i<=r;++i)
    {
        int x=pt[i];
        if (cnt[c[x]]) change(cnt[c[x]],-1);
        cnt[c[x]]+=f;
        if (cnt[c[x]]) change(cnt[c[x]],1);
    }
}
int main()
{
    scanf("%d%d",&n,&m);
    for (int i=1;i<=n;++i) scanf("%d",&c[i]);
    for (int i=1;i"%d%d",&x,&y);
        add(x,y),add(y,x);
    }
    dfs(1,0);
    for (int i=1;i<=m;++i)
    {
        scanf("%d%d",&x,&q[i].k);
        q[i].l=in[x],q[i].r=out[x];q[i].id=i;
    }
    block=sqrt(n);t=(n-1)/block+1;
    for (int i=1;i<=n;++i) num[i]=(i-1)/block+1;
    L[1]=1,R[1]=block;
    for (int i=2;i<=t;++i) L[i]=L[i-1]+block,R[i]=R[i-1]+block;R[t]=n;
    sort(q+1,q+m+1,cmp);
    modui(q[1].l,q[1].r,1);
    q[q[1].id].ans=query(q[1].k);
    for (int i=2;i<=m;++i)
    {
        if (q[i-1].l<q[i].l) modui(q[i-1].l,q[i].l-1,-1);
        else modui(q[i].l,q[i-1].l-1,1);
        if (q[i-1].r<q[i].r) modui(q[i-1].r+1,q[i].r,1);
        else modui(q[i].r+1,q[i-1].r,-1);
        q[q[i].id].ans=query(q[i].k);
    }
    for (int i=1;i<=m;++i) printf("%d\n",q[i].ans);
}

你可能感兴趣的:(题解,莫队,分块)