cf375D. Tree and Queries

链接

点击跳转

题解

用dsu on tree艹过去了…

这题也可以莫队

代码(dsu on tree)

#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#define iinf 0x3f3f3f3f
#define linf (1ll<<60)
#define eps 1e-8
#define maxn 100010
#define maxe 200010
#define cl(x) memset(x,0,sizeof(x))
#define rep(_,__) for(_=1;_<=(__);_++)
#define em(x) emplace(x)
#define emb(x) emplace_back(x)
#define emf(x) emplace_front(x)
#define fi first
#define se second
using namespace std;
using namespace __gnu_pbds;
typedef long long ll;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
int read(ll x=0)
{
    int c, f(1);
    for(c=getchar();!isdigit(c);c=getchar())if(c=='-')f=-f;
    for(;isdigit(c);c=getchar())x=x*10+c-0x30;
    return f*x;
}
struct Graph
{
    int etot, head[maxn], to[maxe], next[maxe], w[maxe];
    void clear(int N)
    {
        for(int i=1;i<=N;i++)head[i]=0;
        etot=0;
    }
    void adde(int a, int b, int c=0){to[++etot]=b;w[etot]=c;next[etot]=head[a];head[a]=etot;}
}G;
struct ShuLianPouFen
{
    int size[maxn], top[maxn], tid[maxn], tim, untid[maxn], deep[maxn], son[maxn], fa[maxn];
    void dfs1(Graph &G, int pos)
    {
        int p, v;
        size[pos]=1;
        for(p=G.head[pos];p;p=G.next[p])
        {
            if((v=G.to[p])==fa[pos])continue;
            fa[v]=pos;
            deep[v]=deep[pos]+1;
            dfs1(G,v);
            if(size[v]>size[son[pos]])son[pos]=v;
            size[pos]+=size[v];
        }
    }
    void dfs2(Graph &G, int pos, int tp)
    {
        int p, v;
        top[pos]=tp;
        tid[pos]=++tim;
        untid[tid[pos]]=pos;
        if(son[pos])dfs2(G,son[pos],tp);
        for(p=G.head[pos];p;p=G.next[p])
            if((v=G.to[p])!=fa[pos] and v!=son[pos])dfs2(G,v,v);
    }
    void run(Graph &G, int root)
    {
        tim=0;
        deep[root]=1;
        dfs1(G,root);
        dfs2(G,root,root);
    }
}sp;
int n, m, k[maxn], ans[maxn], cnt[maxn], c[maxn], forb, tmp[maxn];
vector<int> qlis[maxn];
void upd(int c, int opt)
{
    if(opt==1)
    {
        cnt[c]++;
        tmp[cnt[c]]++;
    }
    else
    {
        tmp[cnt[c]]--;
        cnt[c]--;
    }
}
void force(int pos, int pre, int opt)
{
    upd(c[pos],opt);
    for(auto p=G.head[pos];p;p=G.next[p])
        if(G.to[p]!=pre and G.to[p]!=forb)force(G.to[p],pos,opt);
}
void dfs(int pos, int pre, int H)
{
    for(auto p=G.head[pos];p;p=G.next[p])
        if(G.to[p]!=pre and G.to[p]!=sp.son[pos])
            dfs(G.to[p],pos,0);
    if(sp.son[pos])dfs(sp.son[pos],pos,1);
    forb=sp.son[pos];
    force(pos,pre,+1);
    for(auto q:qlis[pos])ans[q]=tmp[k[q]];
    forb=0;
    if(H==0)force(pos,pre,-1);
}
int main()
{
    int i, u, v;
    n=read(), m=read();
    rep(i,n)c[i]=read();
    rep(i,n-1)
    {
        u=read(), v=read();
        G.adde(u,v), G.adde(v,u);
    }
    rep(i,m)
    {
        v=read(), k[i]=read();
        qlis[v].emb(i);
    }
    sp.run(G,1);
    dfs(1,0,0);
    rep(i,m)printf("%d\n",ans[i]);
    return 0;
}

代码(莫队)

#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#define iinf 0x3f3f3f3f
#define linf (1ll<<60)
#define eps 1e-8
#define maxn 100010
#define maxe 200010
#define cl(x) memset(x,0,sizeof(x))
#define rep(_,__) for(_=1;_<=(__);_++)
#define em(x) emplace(x)
#define emb(x) emplace_back(x)
#define emf(x) emplace_front(x)
#define fi first
#define se second
using namespace std;
using namespace __gnu_pbds;
typedef long long ll;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
ll read(ll x=0)
{
    ll c, f(1);
    for(c=getchar();!isdigit(c);c=getchar())if(c=='-')f=-f;
    for(;isdigit(c);c=getchar())x=x*10+c-0x30;
    return f*x;
}
struct Graph
{
    int etot, head[maxn], to[maxe], next[maxe], w[maxe];
    void clear(int N)
    {
        for(int i=1;i<=N;i++)head[i]=0;
        etot=0;
    }
    void adde(int a, int b, int c=0){to[++etot]=b;w[etot]=c;next[etot]=head[a];head[a]=etot;}
}G;
ll ltid[maxn], rtid[maxn], tim, tmp[maxn];
ll n, m, k[maxn], ans[maxn], cnt[maxn], c[maxn], l[maxn], r[maxn], id[maxn], col[maxn], S=316;
void dfs(ll pos, ll pre)
{
    ltid[pos]=++tim;
    col[tim]=c[pos];
    for(auto p=G.head[pos];p;p=G.next[p])
        if(G.to[p]!=pre)
            dfs(G.to[p],pos);
    rtid[pos]=tim;
}
void upd(ll x, ll v)
{
    if(v==1)
    {
        cnt[col[x]]++;
        tmp[cnt[col[x]]]++;
    }
    else
    {
        tmp[cnt[col[x]]]--;
        cnt[col[x]]--;
    }
}
int main()
{
    ll i, u, v;
    n=read(), m=read();
    rep(i,n)c[i]=read();
    rep(i,n-1)
    {
        u=read(), v=read();
        G.adde(u,v), G.adde(v,u);
    }
    dfs(1,0);
    rep(i,m)
    {
        v=read(), k[i]=read();
        l[i]=ltid[v], r[i]=rtid[v];
        id[i]=i;
    }
    sort(id+1,id+m+1,[](ll a, ll b){return l[a]/S==l[b]/S ? r[a]<r[b] : l[a]/S<l[b]/S; });
    ll L=1, R=0;
    rep(i,m)
    {
        for(;L>l[id[i]];L--)upd(L-1,+1);
        for(;R<r[id[i]];R++)upd(R+1,+1);
        for(;L<l[id[i]];L++)upd(L,-1);
        for(;R>r[id[i]];R--)upd(R,-1);
        ans[id[i]]=tmp[k[id[i]]];
    }
    rep(i,m)printf("%lld\n",ans[i]);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值