• CF375D Tree and Queries


    题目

    luogu

    思路

    唯有水题暖人心
    只用子树的树,当然dfs序列
    区间查询出现k次的数字的个数
    nub[i]记录出现次数大于i的数字个数
    发现只是O(1)的转移,想想就OK了

    代码

    ps:为了更好地阅读,我加一段cpp吧

    void add(int x)
    {	
    	hav[x]++;
    	nub[hav[x]]++;
    }
    void delet(int x)
    {
    	nub[hav[x]]--;
    	hav[x]--;
    }
    FOR(i,1,m)
    {
    	while(l > Q[i].s) add(a[b[--l]]);
    	while(l < Q[i].s) delet(a[b[l++]]);
    	while(r < Q[i].t) add(a[b[++r]]);
    	while(r > Q[i].t) delet(a[b[r--]]);
    	Q[i].ans=nub[Q[i].k];
    }
    
    #include <bits/stdc++.h>
    #define FOR(i,a,b) for(int i=a;i<=b;++i)
    using namespace std;
    const int maxn=1e5+7;
    int n,m,a[maxn],b[maxn],begg[maxn],endd[maxn],js,nub[maxn],hav[maxn];;
    int head[maxn<<1],tot,belong[maxn];
    struct node
    {
    	int s,t,k,id,ans;
    }Q[maxn];
    bool cmp1(const node &a,const node &b){	return belong[a.s]==belong[b.s] ? a.t<b.t : a.s<b.s;}
    bool cmp2(const node &a,const node &b){	return a.id<b.id;}
    struct edge
    {
    	int v,nxt;
    }e[maxn<<1];
    void add_edge(int u,int v)
    {
    	e[++tot].v=v;
    	e[tot].nxt=head[u];
    	head[u]=tot;
    }
    int read()
    {
    	int x=0,f=1;char s=getchar();
    	for(;s<'0'||s>'9';s=getchar()) if(s=='-') f=-1;
    	for(;s>='0'&&s<='9';s=getchar()) x=x*10+s-'0';
    	return x*f;
    }
    void dfs(int u,int f)
    {
    	b[++js]=u;
    	begg[u]=js;
    	for(int i=head[u];i;i=e[i].nxt)
    	{
    		int v=e[i].v;
    		if(v==f) continue;
    		dfs(v,u);
    	}
    	endd[u]=js;
    }
    int main()
    {
    	n=read(),m=read();
    	int k=sqrt(n);
    	FOR(i,1,n) a[i]=read();
    	FOR(i,1,n) belong[i]=(i-1)/k+1;
    	FOR(i,1,n-1)
    	{
    		int x=read(),y=read();
    		add_edge(x,y);
    		add_edge(y,x);
    	}
    	dfs(1,0);
    	FOR(i,1,m)
    	{
    		int x=read(),y=read();
    		Q[i].s=begg[x];
    		Q[i].t=endd[x];
    		Q[i].k=y;
    		Q[i].id=i;
    	}
    	sort(Q+1,Q+1+m,cmp1);
    	int l=1,r=0;
    	FOR(i,1,m)
    	{
    		while(l > Q[i].s) hav[a[b[--l]]]++,nub[hav[a[b[l]]]]++;
    		while(l < Q[i].s) nub[hav[a[b[l]]]]--,hav[a[b[l++]]]--;
    		while(r < Q[i].t) hav[a[b[++r]]]++,nub[hav[a[b[r]]]]++;
    		while(r > Q[i].t) nub[hav[a[b[r]]]]--,hav[a[b[r--]]]--;
    		Q[i].ans=nub[Q[i].k];
    	}
    	sort(Q+1,Q+1+m,cmp2);
    	FOR(i,1,m) printf("%d
    ",Q[i].ans);
    }
    
  • 相关阅读:
    微信小程序常用的方法(留着用)
    微信小程序H5预览页面框架(二维码不隐藏)
    微信小程序H5预览页面框架
    关于微信小程序的一点经验
    微信小程序修改单选按钮的默认样式
    Tomcat8升级后URL中特殊字符报错出现原因
    线程的生命周期和状态控制
    多线程相关概率解释
    多线程面试题集锦三
    spring的xml文件的作用与实现原理
  • 原文地址:https://www.cnblogs.com/dsrdsr/p/9812875.html
Copyright © 2020-2023  润新知