[CF375D]Tree and Queries(dfs序+莫队+分块)

题目:

我是超链接

题意:

给定一棵n个点的树,节点带有权值,询问读入v,k,输出以v为根节点的子树有多少出现次数>=k的权值

题解:

这个子树一看就是dfs序啊,这个询问要分块啊,莫队排序似乎不错。
然后问题转化为【在一段已知区间内,出现次数在一段区间内,的数的个数】
之前做过一道题,当时的问题是【在一段已知区间内,数值在一段区间内,的种类数】,我们当时用的是权值分块
这一道题这么说来可以用次数分块,这样修改 O(1) O ( 1 ) ,查询 O(n) O ( n )

代码:

#include 
#include 
#include 
#include 
using namespace std;
const int N=100005;
int tot,nxt[N*2],point[N],v[N*2],block,n,in[N],dfn[N],out[N],a[N],nn,pos[N],have[N],cnt[N],he[N],ans[N];
struct hh{int v,k,id,l,r;}q[N];
int cmp(hh a,hh b){return pos[a.l]<pos[b.l] || (pos[a.l]==pos[b.l] && a.rint x,int y)
{
    ++tot; nxt[tot]=point[x]; point[x]=tot; v[tot]=y;
    ++tot; nxt[tot]=point[y]; point[y]=tot; v[tot]=x;
}
void dfs(int x,int fa)
{
    dfn[++nn]=x; in[x]=nn;
    for (int i=point[x];i;i=nxt[i])
      if (v[i]!=fa) dfs(v[i],x);
    out[x]=nn;
}
void change(int x,int v)
{
    int t=a[dfn[x]];    
    if (cnt[t]) have[cnt[t]]--,he[pos[cnt[t]]]--;   
    cnt[t]+=v;  
    if (cnt[t]) have[cnt[t]]++,he[pos[cnt[t]]]++;
}
int qurry(int x,int y)
{
    if (x>y) return 0;int ans=0;
    if (pos[x]==pos[y]) for (int i=x;i<=y;i++) ans+=have[i];
    else
    {
        int up=min(n,pos[x]*block);
        for (int i=x;i<=up;i++) ans+=have[i];
        up=(pos[y]-1)*block+1;
        for (int i=up;i<=y;i++) ans+=have[i];
        for (int i=pos[x]+1;i<pos[y];i++) ans+=he[i];
    }
    return ans;
}
int main()
{
    int m;scanf("%d%d",&n,&m);
    for (int i=1;i<=n;i++) scanf("%d",&a[i]);
    for (int i=1;iint x,y;scanf("%d%d",&x,&y);
        addline(x,y);
    }
    dfs(1,0);
    block=sqrt(n);
    for (int i=1;i<=n;i++) pos[i]=(i-1)/block+1; 
    for (int i=1;i<=m;i++) scanf("%d%d",&q[i].v,&q[i].k),q[i].l=in[q[i].v],q[i].r=out[q[i].v],q[i].id=i;
    sort(q+1,q+m+1,cmp);
    int l=1,r=0;
    for (int i=1;i<=m;i++)
    {
        while (l<q[i].l) change(l++,-1);
        while (l>q[i].l) change(--l,1);
        while (r<q[i].r) change(++r,1);
        while (r>q[i].r) change(r--,-1);
        ans[q[i].id]=qurry(q[i].k,n);
    }
    for (int i=1;i<=m;i++) printf("%d\n",ans[i]);
}

你可能感兴趣的:(莫队,分块,搜索(dfs序))