BZOJ 4551 [Tjoi2016&Heoi2016]树

本次省选最水的题,暴力可过。
正解可以用树链剖分,或者直接并查集找爸爸就行了。
bzoj 上只能用树链剖分。

#include<iostream>  
#include<cstdio>  
#include<cstdlib>  
#include<cstring>  
#include<cmath>  
#include<algorithm>  
#define F(i,j,n) for(int i=j;i<=n;i++)  
#define D(i,j,n) for(int i=j;i>=n;i--)  
#define ll long long  
#define pa pair<int,int>  
#define N 100005  
using namespace stdint n,m,cnt,tot;  
int head[N],dep[N],l[N],r[N];  
int tag[N*4],mx[N*4];  
struct edge{int next,to;}e[N*2];  
inline int read()  
{  
    int x=0,f=1;char ch=getchar();  
    while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}  
    while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}  
    return x*f;  
}  
inline void add_edge(int x,int y)  
{  
    e[++cnt]=(edge){head[x],y};head[x]=cnt;  
    e[++cnt]=(edge){head[y],x};head[y]=cnt;  
}  
inline void dfs(int x,int f)  
{  
    l[x]=++tot;dep[x]=dep[f]+1;  
    for(int i=head[x];i;i=e[i].next) if (e[i].to!=f) dfs(e[i].to,x);  
    r[x]=tot;  
}  
inline int better(int x,int y)  
{  
    return dep[x]>dep[y]?x:y;  
}  
void pushup(int k)  
{  
    mx[k]=better(mx[k<<1],mx[k<<1|1]);  
}  
void update(int k,int x)  
{  
    tag[k]=better(tag[k],x);  
    mx[k]=better(mx[k],x);  
}  
void pushdown(int k)  
{  
    if (!tag[k]) return;  
    update(k<<1,tag[k]);update(k<<1|1,tag[k]);  
    tag[k]=0;  
}  
void build(int k,int l,int r)  
{  
    tag[k]=0;mx[k]=1;  
    if (l==r) return;  
    int mid=(l+r)>>1;  
    build(k<<1,l,mid);build(k<<1|1,mid+1,r);  
}  
void change(int k,int l,int r,int L,int R,int x)  
{  
    if (l==L&&r==R){update(k,x);return;}  
    int mid=(l+r)>>1;  
    pushdown(k);  
    if (R<=mid) change(k<<1,l,mid,L,R,x);  
    else if (L>mid) change(k<<1|1,mid+1,r,L,R,x);  
    else change(k<<1,l,mid,L,mid,x),change(k<<1|1,mid+1,r,mid+1,R,x);  
    pushup(k);  
}  
int query(int k,int l,int r,int pos)  
{  
    if (l==r) return mx[k];  
    int mid=(l+r)>>1;  
    pushdown(k);  
    if (pos<=mid) return query(k<<1,l,mid,pos);  
    else return query(k<<1|1,mid+1,r,pos);  
}  
int main()  
{  
    n=read();m=read();  
    F(i,1,n-1){int x=read(),y=read();add_edge(x,y);}  
    dfs(1,0);  
    build(1,1,n);  
    F(i,1,m)  
    {  
        char ch=getchar();while (ch!='C'&&ch!='Q') ch=getchar();  
        int x=read();  
        if (ch=='C') change(1,1,n,l[x],r[x],x);  
        else printf("%d\n",query(1,1,n,l[x]));  
    }  
}  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值