1 条题解
-
0
自动搬运
来自洛谷,原作者为

yydtq
haruka na sora搬运于
2025-08-24 22:49:31,当前版本为作者最后更新于2023-08-19 11:05:51,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
众所周知,本题的代码可以不到 2k,那些场上迅速过了的大多都预存了模板,我也不是说这样不行,不过即使不预存模板也能首 A,因为有一个能常数之外偏序掉树剖的数据结构:Link-Cut-Tree!
首先本题的信息具有结合律,可以看作一种矩阵,鱼框的状态只有五种,我们将一条链的信息看作从鱼框的每一种状态开始,经过这条链之后会变成什么状态,吃下了几条阴阳鱼,实现时可以将末三位表示状态:
struct dat{ int p[5];//0,10,20,11,21; dat operator*(const dat &z)const{ return{ ((p[0]>>3)<<3)+z.p[p[0]&7], ((p[1]>>3)<<3)+z.p[p[1]&7], ((p[2]>>3)<<3)+z.p[p[2]&7], ((p[3]>>3)<<3)+z.p[p[3]&7], ((p[4]>>3)<<3)+z.p[p[4]&7] }; } void init(int d){ if(d)*this={3,8,9,4,4}; else *this={1,2,2,8,11}; } void init(){*this={0,1,2,3,4};} void put(){ for(int i=0;i<5;++i) printf("%d%c",p[i]," \n"[i==4]); } }而每次询问的初始状态都是 ,即鱼框里没有鱼,所以将链上的信息合并之后的 除去末三位就是答案。
为了实现方便需要换根,可以将正的和反的信息都存下来,翻转时交换即可。
于是代码很好写:
#include<bits/stdc++.h> using namespace std; const int N=1e5+5; struct dat{ int p[5];//0,10,20,11,21; dat operator*(const dat &z)const{ return{ ((p[0]>>3)<<3)+z.p[p[0]&7], ((p[1]>>3)<<3)+z.p[p[1]&7], ((p[2]>>3)<<3)+z.p[p[2]&7], ((p[3]>>3)<<3)+z.p[p[3]&7], ((p[4]>>3)<<3)+z.p[p[4]&7] }; } void init(int d){ if(d)*this={3,8,9,4,4}; else *this={1,2,2,8,11}; } void init(){*this={0,1,2,3,4};} void put(){ for(int i=0;i<5;++i) printf("%d%c",p[i]," \n"[i==4]); } }s1[N],s2[N],v[N]; int n,q,cl[N],rv[N],t[N][2],f[N]; #define ls t[x][0] #define rs t[x][1] #define tp(x) (t[f[x]][1]==x) #define in(x) (t[f[x]][0]==x||tp(x)) void pp(int x){ s1[x]=s2[x]=v[x]; if(ls)s1[x]=s1[ls]*s1[x],s2[x]=s2[x]*s2[ls]; if(rs)s1[x]=s1[x]*s1[rs],s2[x]=s2[rs]*s2[x]; } void rev(int x){ rv[x]^=1,swap(ls,rs); swap(s1[x],s2[x]); } void pd(int x){ if(rv[x]){ if(ls)rev(ls); if(rs)rev(rs);rv[x]=0; } } void ppd(int x){ if(in(x))ppd(f[x]);pd(x); } void rot(int x){ int y=f[x],k=tp(x),w=t[x][!k]; t[f[w]=t[x][!k]=y][k]=w; if(in(y))t[f[y]][tp(y)]=x; f[x]=f[y],f[y]=x,pp(y); } void splay(int x){ ppd(x); for(int y=f[x];in(x);rot(x),y=f[x]) if(in(y))rot(tp(x)^tp(y)?x:y);pp(x); } void acs(int x){ for(int y=0;x;x=f[y=x]) splay(x),rs=y,pp(x); } int main(){ ios::sync_with_stdio(false); cin>>n>>q; int i,j,k,l,r,x,y; for(x=1;x<=n;++x)cin>>cl[x],v[x].init(cl[x]),pp(x); for(i=1;i<n;++i){ cin>>x>>y; acs(x),splay(x),rev(x),f[x]=y; } s1[0].init(),s1[0].init(); while(q--){ cin>>k>>x; if(k==1)splay(x),v[x].init(cl[x]^=1),pp(x); else{ cin>>y,acs(x),splay(x),rev(x); acs(y),splay(x); printf("%d\n",s1[x].p[0]>>3); } }return 0; }
- 1
信息
- ID
- 8895
- 时间
- 1000ms
- 内存
- 512MiB
- 难度
- 6
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者