Description
link
支持换根和给定两个点,求子树中满足权值相同的方案数
Solution
遥远的国度 \(+\) 一个简单的询问
(上面两个都是题目名称)
推荐卡常数技巧:把没有用的询问都删掉(就是\(l_1,l_2\) 和 \(1\) 或 \(0\) 比关系的时候)
别的不用stl或者不用函数,手写一类的不大好使(蒟蒻的个人经历)
Code
#include
using namespace std;
namespace yspm{
inline int read()
{
int res=0,f=1; char k;
while(!isdigit(k=getchar())) if(k=='-') f=-1;
while(isdigit(k)) res=res*10+k-'0',k=getchar();
return res*f;
}
const int N=5e5+10;
int a[N],b[N],m,n,T,bl[N],fa[N][25],dep[N],st[N],ed[N],head[N],cnt,tot,dfn,block,ans[N*5],p[N];
struct node{
int nxt,to;
}e[N<<1];
inline void add(int u,int v)
{
e[++cnt].nxt=head[u]; e[cnt].to=v; head[u]=cnt;
return ;
}
inline void dfs(int x,int fat)
{
dep[x]=dep[fat]+1; st[x]=++dfn; fa[x][0]=fat; p[dfn]=x;
for(int i=1;(1<x.r;
}
}q[N*16];
int res,l=0,r=0,s1[N],s2[N],opt,rt=1,num;
inline void add1(int x)
{
s1[x]++; res+=s2[x];
return ;
}
inline void del1(int x)
{
s1[x]--; res-=s2[x];
return ;
}
inline void del2(int x)
{
s2[x]--; res-=s1[x];
return ;
}
inline void add2(int x)
{
s2[x]++; res+=s1[x];
return ;
}
int t1[10],t2[10],now,sz,x,y;
inline void calc(int x)
{
if(x==rt)
{
t1[++now]=1,t2[now]=n;
}
else if(!(st[x]<=st[rt]&&ed[rt]<=ed[x]))
{
t1[++now]=st[x]; t2[now]=ed[x];
}
else
{
int p=dep[rt]-dep[x]-1,y=rt;
for(int i=0;i<18;++i)
{
if(p&(1<r1||l2>r2||l1<1||l2<1||r2>n||l2>n) continue;
if(l1>1&&l2>1) q[++tot].fl=1,q[tot].id=num,q[tot].l=l1-1,q[tot].r=l2-1;
q[++tot].fl=1; q[tot].id=num; q[tot].l=r1; q[tot].r=r2;
if(l1>1) q[++tot].fl=-1,q[tot].id=num,q[tot].r=r2,q[tot].l=l1-1;
if(l2>1) q[++tot].fl=-1,q[tot].id=num,q[tot].r=r1,q[tot].l=l2-1;
}
}
}
}
for(int i=1;i<=tot;++i) if(q[i].l>q[i].r) swap(q[i].l,q[i].r);
sort(q+1,q+tot+1);
for(int i=1;i<=tot;++i)
{
while(lq[i].l) del1(a[p[l]]),--l;
while(rq[i].r) del2(a[p[r]]),--r;
ans[q[i].id]+=q[i].fl*res;
}
for(int i=1;i<=num;++i) printf("%d\n",ans[i]);
return 0;
}
}
signed main(){return yspm::main();}