zoukankan      html  css  js  c++  java
  • 【题解】 Luogu CF375D Tree and Queries

    原题传送门

    这道题要用树链剖分,我博客里有对树链剖分的详细介绍

    我博客中对莫队的详细介绍

    莫队好题

    我一上来想写线段树,随后觉得不好写并弃坑

    我们可以看见没有修改操作,钦定莫队

    但这是在树上,所以不能直接用莫队(废话)

    我们要树链剖分,使得节点和节点的子树能在一个区间里(不会树链剖分的出门左转洛咕树链剖分模板

    剩下的就是最基础的莫队,但是前置和后置++,--要注意qaq,我以前写莫队经常因为++,--的问题出锅qaq

    剩下一些细节见程序

    #pragma GCC optimize("O3")
    #include <bits/stdc++.h>
    #define N 100005
    using namespace std;
    inline int read() //io优化
    {
    	register int x=0,f=1;register char ch=getchar();
    	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    	while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
    	return x*f;
    }
    inline void write(register int x)
    {
    	if(!x)putchar('0');if(x<0)x=-x,putchar('-');
    	static int sta[36];int tot=0;
    	while(x)sta[tot++]=x%10,x/=10;
    	while(tot)putchar(sta[--tot]+48);
    }
    struct edge{
    	int to,next;
    }e[N<<1];
    int head[N],cnt;
    struct query{
    	int l,r,id,bl,k;
    }q[N];
    int n,m,blocksize;
    int c[N];
    int in[N],out[N],w[N];
    inline void dfs(register int x,register int fa)
    {
    	in[x]=++cnt;
    	w[cnt]=c[x];
        for (register int i=head[x];i;i=e[i].next)
    	{
            int y=e[i].to;
    		if (y==fa) 
    			continue;
    		dfs(y,x);
        }
    	out[x]=cnt;
    }
    inline bool cmp(register query a,register query b)
    {
    	return a.bl==b.bl?a.r<b.r:a.bl<b.bl;
    }
    int ans[N],f[N],res[N]; //f[i]表示当前颜色为i的节点的个数,ans[i]表示当前出现次数大于等于i的颜色数量,res是最后的结果
    bool inq[N];
    inline void update(register int x)
    {
    	if(inq[x])
    		--ans[f[w[x]]--];
    	else
    		++ans[++f[w[x]]];
    	inq[x]^=1;
    }
    int main()
    {
    	n=read(),m=read();
    	for(register int i=1;i<=n;++i)
    		c[i]=read();
    	for(register int i=1;i<n;++i)
    	{
    		int x=read(),y=read(); //链式前向星建图
    		e[++cnt]=(edge){y,head[x]};
    		head[x]=cnt;
    		e[++cnt]=(edge){x,head[y]};
    		head[y]=cnt;
    	}
    	cnt=0;
    	dfs(1,1); //树剖
    	blocksize=sqrt(n); //莫队块的大小
    	for(register int i=1;i<=m;++i)
    	{
    		int v=read(),k=read();
    		q[i]=(query){in[v],out[v],i,(in[v]-1)/blocksize+1,k};
    	}
    	sort(q+1,q+1+m,cmp);
    	int l=1,r=0;
    	for(register int i=1;i<=m;++i)
    	{
    		int ll=q[i].l,rr=q[i].r;
    		while(l<ll)
    			update(l++);
    		while(l>ll)
    			update(--l);
    		while(r>rr)
    			update(r--);
    		while(r<rr)
    			update(++r);
    		res[q[i].id]=ans[q[i].k];
    	}
    	for(register int i=1;i<=m;++i)
    	{
    		write(res[i]);
    		printf("
    ");
    	}
    	return 0;
     } 
    
  • 相关阅读:
    Unix进程和线程管理及其异同
    UnixIPC之共享内存
    Unix/Linux常用文件操作
    java中int和Integer比较
    JAVA四种引用类型
    JAVA-Exception&Error
    JAVA特性-跨平台/面向对象
    JAVA单向链表实现
    linux安装及配置c++的opencv库
    static_cast、const_cast、dynamic_cast、reinterpret_cast
  • 原文地址:https://www.cnblogs.com/yzhang-rp-inf/p/9954741.html
Copyright © 2011-2022 走看看