您的位置:首页 > 其它

[LCT] BZOJ 4817 [Sdoi2017]树点涂色

2017-05-03 21:33 489 查看
怎么萎事啊 sdoi怎么有这么多原题

看着这么眼熟

就是我们发现这个染色就是LCT上一个access的过程

而一个点到根路径的颜色数就是到根虚边数加1

这个我们可以access的时候顺便在线段树上子树修改下

而两个点之间的路径颜色数就是加一加再减去lca的两倍然后再加1 那个加1是指lca所属的颜色

子树最大值 直接线段树上查咯

#include<cstdio>
#include<cstdlib>
#include<stack>
#include<algorithm>
using namespace std;

inline char nc(){
static char buf[100000],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
inline void read(int &x){
char c=nc(),b=1;
for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;
for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;
}

const int N=100005;
const int K=18;

struct edge{
int u,v,next;
}G[N<<1];
int head
,inum;
inline void add(int u,int v,int p){
G[p].u=u; G[p].v=v; G[p].next=head[u]; head[u]=p;
}
#define V G[p].v

int size
,depth
,fat
[K];
int pre
,clk,back
;

inline void dfs(int u,int fa){
fat[u][0]=fa; depth[u]=depth[fa]+1;
size[u]=1; pre[u]=++clk; back[clk]=u;
for (int k=1;k<K;k++) fat[u][k]=fat[fat[u][k-1]][k-1];
for (int p=head[u];p;p=G[p].next)
if (V!=fa)
dfs(V,u),size[u]+=size[V];
}
inline int LCA(int u,int v){
if (depth[u]<depth[v]) swap(u,v);
for (int k=K-1;~k;k--)
if ((depth[u]-depth[v])>>k&1)
u=fat[u][k];
if (u==v) return u;
for (int k=K-1;~k;k--)
if (fat[u][k]!=fat[v][k])
u=fat[u][k],v=fat[v][k];
return fat[u][0];
}

struct SEG{
int T[N<<2],F[N<<2];
inline void Build(int x,int l,int r){
if (l==r){
T[x]=depth[back[l]]-1; return;
}
int mid=(l+r)>>1;
Build(x<<1,l,mid);
Build(x<<1|1,mid+1,r);
T[x]=max(T[x<<1],T[x<<1|1]);
}
inline void mark(int x,int t){
F[x]+=t; T[x]+=t;
}
inline void Add(int x,int l,int r,int ql,int qr,int t){
if (ql<=l && r<=qr){
mark(x,t); return;
}
if (F[x]) mark(x<<1,F[x]),mark(x<<1|1,F[x]),F[x]=0;
int mid=(l+r)>>1;
if (ql<=mid) Add(x<<1,l,mid,ql,qr,t);
if (qr>mid) Add(x<<1|1,mid+1,r,ql,qr,t);
T[x]=max(T[x<<1],T[x<<1|1]);
}
inline int Query(int x,int l,int r,int ql,int qr){
if (ql<=l && r<=qr) return T[x];
if (F[x]) mark(x<<1,F[x]),mark(x<<1|1,F[x]),F[x]=0;
int mid=(l+r)>>1,ret=-1<<30;
if (ql<=mid) ret=max(ret,Query(x<<1,l,mid,ql,qr));
if (qr>mid) ret=max(ret,Query(x<<1|1,mid+1,r,ql,qr));
return ret;
}
}Seg;

int n;

inline void Add(int x,int t){
Seg.Add(1,1,n,pre[x],pre[x]+size[x]-1,t);
}
inline int Query(int x){
return Seg.Query(1,1,n,pre[x],pre[x])+1;
}

struct node{
node *ch[2],*f;
bool dir(){ return f->ch[1]==this; }
bool isr(){ return !f || (f->ch[0]!=this && f->ch[1]!=this); }
void setc(node *c,int d){ ch[d]=c; if (c) c->f=this; }
//void push(){ }
//void upd(){ }
}pool
;

inline void rot(node *x){
node *p=x->f; bool d=x->dir();
if (!p->isr()) p->f->setc(x,p->dir()); else x->f=p->f;
p->setc(x->ch[d^1],d),x->setc(p,d^1);// p->upd();
}
//stack<node*> sta;
inline void splay(node *x){
//node *q=x; while (!q->isr()) sta.push(q),q=q->f; sta.push(q);
//while (!sta.empty()) sta.top()->push(),sta.pop();
while (!x->isr())
if (x->f->isr()) rot(x);
else if (x->dir()==x->f->dir()) rot(x->f),rot(x);
else rot(x),rot(x);
//x->upd();
}
inline node *frt(node *x){
splay(x); for (;/*x->push(),*/x->ch[0];x=x->ch[0]); return x;
}
inline void expose(node *x){
for (node *q=NULL;x;q=x,x=x->f){
splay(x);
node *ch=x->ch[1]; x->ch[1]=NULL;
if (ch) Add(frt(ch)-pool,1);
if (q) Add(frt(q)-pool,-1);
x->ch[1]=q;
//x->upd();
}
}

int main(){
int Q,order,iu,iv;
freopen("t.in","r",stdin);
freopen("t.out","w",stdout);
read(n); read(Q);
for (int i=1;i<n;i++) read(iu),read(iv),add(iu,iv,++inum),add(iv,iu,++inum);
dfs(1,0);
Seg.Build(1,1,n);
for (int i=2;i<=n;i++) pool[i].f=pool+fat[i][0];
while (Q--){
read(order); read(iu);
if (order==1){
expose(pool+iu);
}else if (order==2){
read(iv); int lca=LCA(iu,iv);
printf("%d\n",Query(iu)+Query(iv)-2*Query(lca)+1);
}else{
printf("%d\n",Seg.Query(1,1,n,pre[iu],pre[iu]+size[iu]-1)+1);
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: