Codeforces 375D Tree and Queries dfs序+莫队

这题好题啊.
我发现我没有写过莫队算法的博客.以后我会把博客加上去的.
先看看这题吧.
Codeforces 375D Tree and Queries
给一棵 1 为根的树,每个节点有一种颜色; m 个询问,询问 v 为根的子树中出现次数 k 的颜色有多少种.

只有询问.我们考虑莫队.
只有子树.我们考虑dfs序.
以1为根跑出dfs序并重新编号,用dfn和edf两个数组标明每个点控制的子树.
接下来莫队离线排序搞一下,用cnt数组维护每一种颜色出现的次数.
sum数组维护每一种颜色出现的次数分别出现的次数.(这个说法比较诡异).

然后按照莫队处理一下就可以了.

#include<bits/stdc++.h> //Ithea Myse Valgulious
namespace chtholly{
typedef long long ll;
#define re0 register int
#define rec register char
#define rel register ll
#define gc getchar
#define pc putchar
#define p32 pc(' ')
#define pl puts("")
/*By Citrus*/
inline int read(){
  re0 x=0,f=1;rec c=gc();
  for (;!isdigit(c);c=gc()) f^=c=='-';
  for (;isdigit(c);c=gc()) x=x*10+c-'0';
  return x*(f?1:-1);
  }
inline void read(rel &x){
  x=0;re0 f=1;rec c=gc();
  for (;!isdigit(c);c=gc()) f^=c=='-';
  for (;isdigit(c);c=gc()) x=x*10+c-'0';
  x*=f?1:-1;
  }
template <typename mitsuha>
inline int write(mitsuha x){
  if (!x) return pc(48);
  if (x<0) x=-x,pc('-');
  re0 bit[20],i,p=0;
  for (;x;x/=10) bit[++p]=x%10;
  for (i=p;i;--i) pc(bit[i]+48);
  }
inline char fuhao(){
  rec c=gc();
  for (;isspace(c);c=gc());
  return c;
  }
}using namespace chtholly;
using namespace std;
const int yuzu=1e5;
typedef int fuko[yuzu|10];
vector<int> lj[yuzu|10];
fuko a,dfn,edf,cnt,ans,sum,col;
int n=read(),m=read(),id,block=sqrt(n);

#define bl(x) ((x)/block)
#define all(u) dfn[u],edf[u]
void dfs(int u,int fa){
dfn[u]=++id;
col[id]=u;
for (int v:lj[u]) if (v^fa) dfs(v,u);
edf[u]=id;
}

struct query{
int l,r,k,id;
bool operator <(const query &b) const{
  return bl(l)^bl(b.l)?l<b.l:r<b.r;
  }
}q[yuzu|10];

int nowl=1,nowr;
void add(int x){sum[++cnt[a[col[x]]]]++;}
void del(int x){sum[cnt[a[col[x]]]--]--;}
int main(){
re0 i;
for (i=1;i<=n;++i) a[i]=read();
for (i=1;i<n;++i){
  int u=read(),v=read();
  lj[u].push_back(v);
  lj[v].push_back(u);
  }
dfs(1,0);
for (i=1;i<=m;++i){
  int u=read(),k=read();
  q[i]=query{all(u),k,i};
  }
sort(q+1,q+m+1);
for (i=1;i<=m;++i){
  for (;nowl<q[i].l;) del(nowl++);
  for (;nowl>q[i].l;) add(--nowl);
  for (;nowr<q[i].r;) add(++nowr);
  for (;nowr>q[i].r;) del(nowr--);
  ans[q[i].id]=sum[q[i].k];
  }
for (i=1;i<=m;++i) write(ans[i]),pl;
}

猜你喜欢

转载自blog.csdn.net/qq_31908675/article/details/80113525