zoukankan      html  css  js  c++  java
  • BZOJ4551: [Tjoi2016&Heoi2016]树

    BZOJ4551: [Tjoi2016&Heoi2016]树

    Description

    在2016年,佳媛姐姐刚刚学习了树,非常开心。现在他想解决这样一个问题:给定一颗有根树(根为1),有以下两种操作:
    1. 标记操作:对某个结点打上标记(在最开始,只有结点1有标记,其他结点均无标记,而且对于某个结点,可以打多次标记。)
    2. 询问操作:询问某个结点最近的一个打了标记的祖先(这个结点本身也算自己的祖先)
    你能帮帮他吗?

    Input

    输入第一行两个正整数N和Q分别表示节点个数和操作次数
    接下来N-1行,每行两个正整数u,v(1≤u,v≤n)表示u到v有一条有向边
    接下来Q行,形如“opernum”oper为“C”时表示这是一个标记操作,oper为“Q”时表示这是一个询问操作
    对于每次询问操作,1 ≤ N, Q ≤ 100000。

    Output

    输出一个正整数,表示结果

    Sample Input

    5 5
    1 2
    1 3
    2 4
    2 5
    Q 2
    C 2
    Q 2
    Q 5
    Q 3

    Sample Output

    1
    2
    2
    1
    题解Here!
    树链剖分。
    打上标记就是修改为剖分后的节点标号。
    询问就是求最大值。
    附代码:
    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #define LSON rt<<1
    #define RSON rt<<1|1
    #define DATA(x) b[x].data
    #define LSIDE(x) b[x].l
    #define RSIDE(x) b[x].r
    #define MAXN 100010
    using namespace std;
    int n,m,c=1,d=1;
    int head[MAXN],deep[MAXN],size[MAXN],son[MAXN],fa[MAXN],top[MAXN],id[MAXN],nid[MAXN];
    struct node1{
        int next,to;
    }a[MAXN<<1];
    struct node2{
        int data,l,r;
    }b[MAXN<<2];
    inline int read(){
    	int date=0,w=1;char c=0;
    	while(c<'0'||c>'9'){if(c=='-')w=-1;c=getchar();}
    	while(c>='0'&&c<='9'){date=date*10+c-'0';c=getchar();}
    	return date*w;
    }
    inline void add(int x,int y){
        a[c].to=y;a[c].next=head[x];head[x]=c++;
    	a[c].to=x;a[c].next=head[y];head[y]=c++;
    }
    void dfs1(int rt){
        son[rt]=0;size[rt]=1;
        for(int i=head[rt];i;i=a[i].next){
            int will=a[i].to;
            if(!deep[will]){
                deep[will]=deep[rt]+1;
                fa[will]=rt;
                dfs1(will);
                size[rt]+=size[will];
                if(size[son[rt]]<size[will])son[rt]=will;
            }
        }
    }
    void dfs2(int rt,int f){
        nid[d]=rt;id[rt]=d++;top[rt]=f;
        if(son[rt])dfs2(son[rt],f);
        for(int i=head[rt];i;i=a[i].next){
            int will=a[i].to;
            if(will!=fa[rt]&&will!=son[rt])
            dfs2(will,will);
        }
    }
    inline void pushup(int rt){
        DATA(rt)=max(DATA(LSON),DATA(RSON));
    }
    void buildtree(int l,int r,int rt){
        int mid;
        LSIDE(rt)=l;
        RSIDE(rt)=r;
        if(l==r){
            DATA(rt)=0;
            return;
        }
        mid=l+r>>1;
        buildtree(l,mid,LSON);
        buildtree(mid+1,r,RSON);
        pushup(rt);
    }
    void update(int l,int r,int rt){
        int mid;
        if(l<=LSIDE(rt)&&RSIDE(rt)<=r){
            DATA(rt)=l;
            return;
        }
        mid=LSIDE(rt)+RSIDE(rt)>>1;
        if(l<=mid)update(l,r,LSON);
        if(mid<r)update(l,r,RSON);
        pushup(rt);
    }
    int query(int l,int r,int rt){
        int mid,ans=0;
        if(l<=LSIDE(rt)&&RSIDE(rt)<=r)return DATA(rt);
        mid=LSIDE(rt)+RSIDE(rt)>>1;
        if(l<=mid)ans=max(ans,query(l,r,LSON));
        if(mid<r)ans=max(ans,query(l,r,RSON));
        return ans;
    }
    void work1(int x,int y){
        int s=0;
        while(top[x]!=top[y]){
            if(deep[top[x]]<deep[top[y]])swap(x,y);
            s=max(s,query(id[top[x]],id[x],1));
            x=fa[top[x]];
        }
        if(deep[x]>deep[y])swap(x,y);
        s=max(s,query(id[x],id[y],1));
        printf("%d
    ",nid[s]);
        return;
    }
    void work(){
        char ch[2];
        int x;
        while(m--){
            scanf("%s",ch);x=read();
            if(ch[0]=='C')update(id[x],id[x],1);
            if(ch[0]=='Q')work1(1,x);
        }
    }
    void init(){
        int x,y;
        n=read();m=read();
        for(int i=1;i<n;i++){
            x=read();y=read();
            add(x,y);
        }
        deep[1]=1;
        dfs1(1);
        dfs2(1,1);
        buildtree(1,n,1);
        update(id[1],id[1],1);
    }
    int main(){
        init();
        work();
    	return 0;
    }
    
  • 相关阅读:
    在千万级的数据库查询中,如何提高效率?
    SQL的触发器和存储过程详解
    如何提高mysql的安全性?
    mysql的触发器
    HDU5564 Clarke and digits
    JOI2014Final 飞天鼠
    Topcoder10073 SRM418 BarracksEasy
    Topcoder9902 SRM416 DancingCouples
    Topcoder8307 SRM390 SetOfPatterns
    POJ1741 Tree(点分治)
  • 原文地址:https://www.cnblogs.com/Yangrui-Blog/p/9043403.html
Copyright © 2011-2022 走看看