cf375d

这道题树上莫队显然的吧。。

还有可以写启发式合并

总结:写两个程序的时候都出现了小错。莫队是++x和x++位置写错,启发式合并是dfs时反复用了同一个数组。。。。

我是傻子吗???

#include<cstdio>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<string>
#include<cstring>
#include<cctype>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<iomanip>
#include<sstream>
#include<cstdlib>
#include<ctime>
#include<list>
#include<deque>
#include<bitset>
#include<fstream>
#define ld double
#define ull unsigned long long
#define ll long long
#define pii pair<int,int >
#define iiii pair<int,pii >
#define mp make_pair
#define INF 1000000000
#define MOD 1000000007
#define rep(i,x) for(int (i)=0;(i)<(x);(i)++)
inline int getint()
{
	int x=0,p=1;char c=getchar();
	while (c<=32)c=getchar();
	if(c==45)p=-p,c=getchar();
	while (c>32)x=x*10+c-48,c=getchar();
	return x*p;
}
using namespace std;
//
const int maxn=1e5+5;
int n,t,res[maxn],c[maxn];
struct node
{
	map<int,int>M;
	vector<int>pre;
	int cnt;
	node(){pre.push_back(n);cnt=0;}
	int precnt(int k)
	{
		if(k>=pre.size())return 0;
		return pre.back()-pre[k-1];
	}
};
vector<pii >q[maxn];
vector<int>G[maxn];
vector<node*>son;
map<int,int>::iterator it;
//
node* fmerge(node *x,node *y)
{
	if(x->cnt<y->cnt)swap(x,y);
	x->cnt+=y->cnt;
	for(it=y->M.begin();it!=y->M.end();it++)
	{
		int col=it->first,cc=it->second;
		rep(i,cc)
		{
			x->M[col]++;
			int v=x->M[col];
			if(v==x->pre.size())x->pre.emplace_back(x->pre.back());
			x->pre[v-1]--;
		}
	}
	return x;
}
node* dfs(int x,int p)
{
	vector<node*>son;
	rep(i,G[x].size())if(G[x][i]!=p)
		son.emplace_back(dfs(G[x][i],x));
	node *ans;
	if(!son.size())ans=new node();
	else ans=son[0];
	for(int i=1;i<son.size();i++)ans=fmerge(son[i],ans);
	ans->M[c[x]]++;int v=ans->M[c[x]];
	if(v==ans->pre.size())ans->pre.emplace_back(ans->pre.back());
	ans->pre[v-1]--;
	rep(i,q[x].size())
	{
		int xx=q[x][i].first,yy=q[x][i].second;
		res[yy]=ans->precnt(xx);
	}
	ans->cnt++;
	return ans;
}
int main()
{
	n=getint();t=getint();
	rep(i,n)c[i]=getint();
	rep(i,n-1)
	{
		int x=getint()-1,y=getint()-1;
		G[x].emplace_back(y);
		G[y].emplace_back(x);
	}
	rep(i,t)
	{
		int x=getint()-1,y=getint();
		q[x].emplace_back(mp(y,i));
	}
	dfs(0,-1);
	rep(i,t)printf("%d\n",res[i]);
	return 0;
}
#include<cstdio>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<string>
#include<cstring>
#include<cctype>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<iomanip>
#include<sstream>
#include<cstdlib>
#include<ctime>
#include<list>
#include<deque>
#include<bitset>
#include<fstream>
#define ld double
#define ull unsigned long long
#define ll long long
#define iiii pair<int,pii >
#define mp make_pair
#define INF 1000000000
#define MOD 1000000007
#define rep(i,x) for(int (i)=0;(i)<(x);(i)++)
inline int getint()
{
	int x=0,p=1;char c=getchar();
	while (c<=32)c=getchar();
	if(c==45)p=-p,c=getchar();
	while (c>32)x=x*10+c-48,c=getchar();
	return x*p;
}
using namespace std;
//
const int B=500;
struct pii{int c,u;};
const int maxn=1e5+5;
vector<int>G[maxn];
int n,t,c[maxn],ans[maxn],ord[maxn],C[maxn],cnt,L[maxn],R[maxn],id[maxn],res[maxn];
vector<pii >v;
//
bool cmp(int xx,int yy)
{
	int x=L[v[xx].c],y=R[v[xx].c],z=L[v[yy].c],w=R[v[yy].c];
	if(x/B==z/B)return y<w;
	return x<z;
}
void dfs(int x,int p)
{
	ord[x]=cnt;
	C[cnt]=c[x];
	L[cnt]=ord[x];cnt++;
	rep(i,G[x].size())if(G[x][i]!=p)
		dfs(G[x][i],x);
	R[ord[x]]=cnt-1;	
	//cout<<x+1<<" "<<ord[x]<<" "<<L[ord[x]]<<" "<<R[ord[x]]<<" "<<C[ord[x]]<<endl;
}
int main()
{
	n=getint();t=getint();
	rep(i,n)c[i]=getint();
	rep(i,n-1)
	{
		int x=getint()-1,y=getint()-1;
		G[x].emplace_back(y);
		G[y].emplace_back(x);
	}
	dfs(0,-1);
	rep(i,t)
	{
		id[i]=i;
		int xx=getint()-1,x=ord[xx],y=getint();
		v.push_back((pii){x,y});
	}
	sort(id,id+t,cmp);
	int l=1,r=0;
	memset(c,0,sizeof(c));
	rep(ii,t)
	{
		int i=id[ii];
		while (r<R[v[i].c])ans[++c[C[++r]]]++;
		while (l>L[v[i].c])ans[++c[C[--l]]]++;
		while (r>R[v[i].c])--ans[c[C[r--]]--];
		while (l<L[v[i].c])--ans[c[C[l++]]--];
		res[i]=ans[v[i].u];
	}
	rep(i,t)printf("%d\n",res[i]);
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值