Ynoi2016 这是我自己发明的
Posted yspm
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Ynoi2016 这是我自己发明的相关的知识,希望对你有一定的参考价值。
Description
支持换根和给定两个点,求子树中满足权值相同的方案数
Solution
遥远的国度 (+) 一个简单的询问
(上面两个都是题目名称)
推荐卡常数技巧:把没有用的询问都删掉(就是(l_1,l_2) 和 (1) 或 (0) 比关系的时候)
别的不用stl或者不用函数,手写一类的不大好使(蒟蒻的个人经历)
Code
#include<bits/stdc++.h>
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<<i)<=dep[x];++i) fa[x][i]=fa[fa[x][i-1]][i-1];
for(int i=head[x];i;i=e[i].nxt) if(e[i].to==fat) continue; else dfs(e[i].to,x);
ed[x]=dfn;
return ;
}
struct ask{
int l,r,fl,id;
inline void init(int a,int b,int c,int d){l=a,r=b,fl=c,id=d; return ;}
bool operator <(const ask &x) const
{
if(bl[l]!=bl[x.l]) return l<x.l;
if(bl[l]&1) return r<x.r;
return r>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<<i)) y=fa[y][i];
}
t1[++now]=1; t2[now]=st[y]-1;
t1[++now]=ed[y]+1; t2[now]=n;
}return ;
}
#define l1 t1[i]
#define l2 t1[j]
#define r1 t2[i]
#define r2 t2[j]
signed main()
{
n=read(); T=read(); block=sqrt(n);
for(int i=1;i<=n;++i) bl[i]=(i-1)/block+1,a[i]=read(),b[++m]=a[i];
sort(b+1,b+m+1); m=unique(b+1,b+m+1)-b-1;
for(int i=1;i<=n;++i) a[i]=lower_bound(b+1,b+m+1,a[i])-b;
for(int i=1,u,v;i<n;++i) u=read(),v=read(),add(u,v),add(v,u);
dfs(1,0);
while(T--)
{
opt=read();
if(opt==1) rt=read();
else
{
x=read(),y=read(); ++num; now=0; calc(x); sz=now; calc(y);
for(int i=1;i<=sz;++i)
{
for(int j=sz+1;j<=now;++j)
{
if(l1>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(l<q[i].l) ++l,add1(a[p[l]]);
while(l>q[i].l) del1(a[p[l]]),--l;
while(r<q[i].r) ++r,add2(a[p[r]]);
while(r>q[i].r) del2(a[p[r]]),--r;
ans[q[i].id]+=q[i].fl*res;
}
for(int i=1;i<=num;++i) printf("%d
",ans[i]);
return 0;
}
}
signed main(){return yspm::main();}
以上是关于Ynoi2016 这是我自己发明的的主要内容,如果未能解决你的问题,请参考以下文章
「Luogu P4689 [Ynoi2016]这是我自己的发明」
「Luogu P4689 [Ynoi2016]这是我自己的发明」