bzoj4551: [Tjoi2016&Heoi2016]树

来源:互联网 发布:类似易企秀的软件 编辑:程序博客网 时间:2024/06/04 18:37

链接

  http://www.lydsy.com/JudgeOnline/problem.php?id=4551

题解

  还行吧这道题,不是特别傻逼。
  一个点被标记,显然会影响到子树中的所有点。
  显然每次查询会选择这个点到根的路径上深度最深的那个祖先点作为答案。

做法一

  离线并查集,ftm用了这种方法,倒序变成删除标记。剩下的细节请读者思考。

做法二

  LCT直接暴力,一开始想用这个,但是看到题目下方:新加了九组测试数据,我就知道它想卡这个。弃疗。

做法三

  这个算法我感觉长得比较像正解。
  算出dfs序,每次修改,就把这个点的子树对这个点的深度取个max。
  线段树区间取max,单点查询。

代码

//线段树 #include <cstdio>#include <algorithm>#define maxn 200010using namespace std;int tid[maxn], ltid[maxn], rtid[maxn], untid[maxn], N, Q, nex[maxn], to[maxn],    head[maxn], tot, ndtot, deep[maxn];inline void adde(int a, int b){to[++tot]=b;nex[tot]=head[a];head[a]=tot;}struct segtree{int l, r, tag, max; segtree *ch[2];}pool[maxn], *root;inline int read(int x=0){    char c=getchar();    while(c<48 or c>57)c=getchar();    while(c>=48 and c<=57)x=(x<<1)+(x<<3)+c-48, c=getchar();    return x;}inline char readc(){    char c=getchar();    while(c!='Q' and c!='C')c=getchar();    return c;}void dfs(int pos){    int p;    ltid[pos]=tid[pos]=++tid[0];untid[tid[pos]]=pos;    for(p=head[pos];p;p=nex[p])deep[to[p]]=deep[pos]+1, dfs(to[p]);    rtid[pos]=tid[0];}void build(segtree *p, int l, int r){    int mid=(l+r)>>1;    p->l=l, p->r=r;    if(l==r)return;    build(p->ch[0]=pool+ ++ndtot,l,mid);    build(p->ch[1]=pool+ ++ndtot,mid+1,r);}void init(){    int a, b, i;    N=read(), Q=read();    for(i=1;i<N;i++)a=read(), b=read(), adde(a,b);    deep[1]=1, dfs(1);    build(root=pool+ ++ndtot,1,N);}inline void u(int a, int &b){if(deep[a]>deep[b])b=a;}inline void tag(segtree *p, int tag){u(tag,p->tag);}inline void pushdown(segtree *p){    u(p->tag,p->max);    if(p->ch[0])tag(p->ch[0],p->tag),tag(p->ch[1],p->tag);}inline void update(segtree *p){    if(!p->ch[0])return;    pushdown(p->ch[0]), pushdown(p->ch[1]);    if(deep[p->ch[0]->max]>deep[p->ch[1]->max])p->max=p->ch[0]->max;    else p->max=p->ch[1]->max;}void segchg(segtree *p, int l, int r, int a){    pushdown(p);    int mid=(p->l+p->r)>>1;    if(l<=p->l and r>=p->r){tag(p,a);return;}    if(l<=mid)segchg(p->ch[0],l,r,a);    if(r>mid)segchg(p->ch[1],l,r,a);    update(p);}int segmax(segtree *p, int l, int r){    pushdown(p);    int mid=(p->l+p->r)>>1, ans=0;    if(l<=p->l and r>=p->r)return p->max;    if(l<=mid)u(segmax(p->ch[0],l,r),ans);    if(r>mid)u(segmax(p->ch[1],l,r),ans);    return ans;}void work(){    int pos;    char type;    tag(root,1);    while(Q--)    {        type=readc();        pos=read();        if(type=='C')segchg(root,ltid[pos],rtid[pos],pos);        else printf("%d\n",segmax(root,tid[pos],tid[pos]));    }}int main(){    init();    work();    return 0;}
0 0
原创粉丝点击