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;
     } 
    
  • 相关阅读:
    POJ 3041 Asteroids 最小点覆盖 == 二分图的最大匹配
    POJ 3083 Children of the Candy Corn bfs和dfs
    POJ 2049 Finding Nemo bfs 建图很难。。
    POJ 2513 Colored Sticks 字典树、并查集、欧拉通路
    POJ 1013 Counterfeit Dollar 集合上的位运算
    POJ 2965 The Pilots Brothers' refrigerator 位运算枚举
    无聊拿socket写的100以内的加法考试。。。
    POJ 1753 Flip Game
    初学socket,c语言写的简单局域网聊天
    汇编语言 复习 第十一章 标志寄存器
  • 原文地址:https://www.cnblogs.com/yzhang-rp-inf/p/9954741.html
Copyright © 2011-2022 走看看