同BZOJ3779。
SDOI出原题,还是弱化版的。
吃枣药丸
#include <map> #include <cmath> #include <queue> #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; #define F(i,j,k) for (int i=j;i<=k;++i) #define D(i,j,k) for (int i=j;i>=k;--i) #define ll long long #define mp make_pair #define maxn 200005 int n,m,data[maxn]; namespace Tree{ int h[maxn],to[maxn],ne[maxn],f[maxn][21],en=0,dep[maxn]; int id[maxn],in[maxn],out[maxn],tot=0; void add(int a,int b) {to[en]=b;ne[en]=h[a];h[a]=en++;} void dfs(int o) { in[o]=++tot; id[tot]=o; for (int i=h[o];i>=0;i=ne[i]) if (to[i]!=f[o][0]) f[to[i]][0]=o,dep[to[i]]=dep[o]+1,dfs(to[i]); out[o]=tot; } void init() { F(i,1,20)F(j,1,n)f[j][i]=f[f[j][i-1]][i-1]; F(i,1,n) data[in[i]]=dep[i]; // F(i,1,n) printf("%d ",id[i]); printf(" "); // F(i,1,n) printf("%d ",data[i]);printf(" "); } int LCA(int a,int b) { if (dep[a]<dep[b]) swap(a,b); int dist=dep[a]-dep[b]; D(i,20,0) if ((dist>>i)&1) a=f[a][i]; if (a==b) return a; D(i,20,0) if (f[a][i]!=f[b][i]) a=f[a][i],b=f[b][i]; return f[b][0]; } } namespace SegTree{ int mx[maxn<<3],tag[maxn<<3]; void update(int o) {mx[o]=max(mx[o<<1],mx[o<<1|1]);} void pushdown(int o) { if (tag[o]!=0) { tag[o<<1]+=tag[o]; tag[o<<1|1]+=tag[o]; mx[o<<1]+=tag[o]; mx[o<<1|1]+=tag[o]; tag[o]=0; } } void build(int o,int l,int r) { if (l==r) { mx[o]=data[l]; tag[o]=0; return ; } pushdown(o); int mid=l+r>>1; build(o<<1,l,mid); build(o<<1|1,mid+1,r); update(o); } void modify(int o,int l,int r,int L,int R,int f) { if (L<=l&&r<=R) { tag[o]+=f; mx[o]+=f; return; } pushdown(o); int mid=l+r>>1; if (R<=mid) return modify(o<<1,l,mid,L,R,f),update(o); else if (L>mid) return modify(o<<1|1,mid+1,r,L,R,f),update(o); else return modify(o<<1,l,mid,L,R,f),modify(o<<1|1,mid+1,r,L,R,f),update(o); } void add(int a,int f) {if (!a) return ;modify(1,1,n,Tree::in[a],Tree::out[a],f);} int querymx(int o,int l,int r,int L,int R) { if (L<=l&&r<=R) return mx[o]; pushdown(o); int mid=l+r>>1; if (R<=mid) return querymx(o<<1,l,mid,L,R); else if (L>mid) return querymx(o<<1|1,mid+1,r,L,R); else return max(querymx(o<<1,l,mid,L,R),querymx(o<<1|1,mid+1,r,L,R)); } } namespace LCT{ int rev[maxn],fa[maxn],ch[maxn][2],sta[maxn],top=0; bool isroot(int o) {return ch[fa[o]][0]!=o&&ch[fa[o]][1]!=o;} void rot(int x) { int y=fa[x],z=fa[y],l,r; if (ch[y][0]==x) l=0; else l=1; r=l^1; if (!isroot(y)) { if (ch[z][0]==y) ch[z][0]=x; else ch[z][1]=x; } fa[x]=z;fa[y]=x;fa[ch[x][r]]=y; ch[y][l]=ch[x][r]; ch[x][r]=y; } void pushdown(int x) { if (rev[x]) { rev[x]^=1; rev[ch[x][0]]^=1; rev[ch[x][1]]^=1; swap(ch[x][0],ch[x][1]); } } void splay(int x) { sta[top=1]=x; for (int i=x;!isroot(i);i=fa[i]) sta[++top]=fa[i]; while(top) pushdown(sta[top--]); while (!isroot(x)) { int y=fa[x]; if (!isroot(y)) { int z=fa[y]; if (ch[z][0]==y^ch[y][0]==x) rot(x); else rot(y); } rot(x); } } int find(int x) { pushdown(x); while (ch[x][0]) x=ch[x][0],pushdown(x); return x; } void access(int x) { for (int t=0;x;t=x,x=fa[x]) { splay(x); SegTree::add(find(ch[x][1]),1); ch[x][1]=t; SegTree::add(find(ch[x][1]),-1); } } } int opt,x,y; int main() { scanf("%d%d",&n,&m); memset(Tree::h,-1,sizeof Tree::h); F(i,2,n) { int a,b; scanf("%d%d",&a,&b); Tree::add(a,b); Tree::add(b,a); } Tree::dep[1]=1;Tree::dfs(1);Tree::init(); F(i,1,n) LCT::fa[i]=Tree::f[i][0]; SegTree::build(1,1,n); F(i,1,m) { scanf("%d",&opt); // cout<<opt<<endl; switch(opt) { case 1: scanf("%d",&x); LCT::access(x); break; case 2: scanf("%d%d",&x,&y); printf("%d ",SegTree::querymx(1,1,n,Tree::in[x],Tree::in[x])+SegTree::querymx(1,1,n,Tree::in[y],Tree::in[y])+1-2*SegTree::querymx(1,1,n,Tree::in[Tree::LCA(x,y)],Tree::in[Tree::LCA(x,y)])); break; case 3: scanf("%d",&x); printf("%d ",SegTree::querymx(1,1,n,Tree::in[x],Tree::out[x]));break; } } }