原题传送门
这道题要用树链剖分,我博客里有对树链剖分的详细介绍
我博客中对莫队的详细介绍
莫队好题
我一上来想写线段树,随后觉得不好写并弃坑
我们可以看见没有修改操作,钦定莫队
但这是在树上,所以不能直接用莫队(废话)
我们要树链剖分,使得节点和节点的子树能在一个区间里(不会树链剖分的出门左转洛咕树链剖分模板)
剩下的就是最基础的莫队,但是前置和后置++,--要注意qaq,我以前写莫队经常因为++,--的问题出锅qaq
剩下一些细节见程序
#pragma GCC optimize("O3")
#include
#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.rll)
update(--l);
while(r>rr)
update(r--);
while(r