• [JLOI2014]松鼠的新家


    [JLOI2014]松鼠的新家

    题目描述

    松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n个房间,并且有n-1根树枝连接,每个房间都可以相互到达,且俩个房间之间的路线都是唯一的。天哪,他居然真的住在”树“上。

    松鼠想邀请****前来参观,并且还指定一份参观指南,他希望**能够按照他的指南顺序,先去a1,再去a2,......,最后到an,去参观新家。可是这样会导致**重复走很多房间,懒惰的**不停地推辞。可是松鼠告诉他,每走到一个房间,他就可以从房间拿一块糖果吃。

    **是个馋家伙,立马就答应了。现在松鼠希望知道为了保证**有糖果吃,他需要在每一个房间各放至少多少个糖果。

    因为松鼠参观指南上的最后一个房间an是餐厅,餐厅里他准备了丰盛的大餐,所以当**在参观的最后到达餐厅时就不需要再拿糖果吃了。

    输入输出格式

    输入格式:

    第一行一个整数n,表示房间个数第二行n个整数,依次描述a1-an

    接下来n-1行,每行两个整数x,y,表示标号x和y的两个房间之间有树枝相连。

    输出格式:

    一共n行,第i行输出标号为i的房间至少需要放多少个糖果,才能让**有糖果吃。

    输入输出样例

    输入样例#1: 
    5
    1 4 5 3 2
    1 2
    2 4
    2 3
    4 5
    输出样例#1: 
    1
    2
    1
    2
    1

    说明

    2<= n <=300000

    Soulution

    树链剖分裸题。

    每次对于一条链上的数加1,注意起点不用放糖,最后终点要减1.

    似乎常数很大

    #include<bits/stdc++.h>
    
    using namespace std;
    
    #define MAXN 300010
    
    inline int read()
    {
        int f=1,x=0;
        char ch;
        do
        {
            ch=getchar();
            if(ch=='-') f=-1;
        }while(ch<'0'||ch>'9');
        do
        {
            x=(x<<3)+(x<<1)+ch-'0';
            ch=getchar();
        }while(ch>='0'&&ch<='9');
        return f*x;
    }
    
    struct node
    {
        int to;
        int next;
    };
    
    int n;
    int a[MAXN];
    int head[MAXN],cnt=0;
    node g[MAXN*2];
    int num[MAXN],top[MAXN],son[MAXN],fa[MAXN],dep[MAXN];
    int tot[MAXN],h=0;
    int add[MAXN<<2];
    
    inline void addedge(int a,int b)
    {
        ++cnt;g[cnt].to=b;g[cnt].next=head[a];head[a]=cnt;return;
    }
    
    inline void dfs1(int x,int f)
    {
        son[x]=0;tot[x]=1;
        for(int i=head[x];i;i=g[i].next)
        {
            int v=g[i].to;
            if(v!=f)
            {
                fa[v]=x;
                dep[v]=dep[x]+1;
                dfs1(v,x);
                tot[x]+=tot[v];
                if(tot[son[x]]<tot[v]) son[x]=v;
            }
        }
    }
    
    inline void dfs2(int x,int now)
    {
        top[x]=now;num[x]=++h;
        if(son[x]) dfs2(son[x],now);
        for(int i=head[x];i>0;i=g[i].next)
        {
            int v=g[i].to;
            if(v!=son[x]&&v!=fa[x])
            {
                dfs2(v,v);
            }
        }
    }
    
    struct s_tree
    {
        int l;
        int r;
        int sum;
        inline int mid()
        {
            return (l+r)>>1;    
        } 
    }tree[MAXN<<2]; 
    
    #define lc o<<1
    #define rc o<<1|1 
    
    inline void build(int o,int l,int r)
    {
        tree[o].l=l;tree[o].r=r;tree[o].sum=0;
        if(l==r) return;
        else 
        {
            int mid=tree[o].mid();
            build(lc,l,mid);
            build(rc,mid+1,r);
        }
    }
    
    inline void pushdown(int o)
    {
        if(!add[o]) return;
        tree[lc].sum+=(tree[lc].r-tree[lc].l+1)*add[o];
        tree[rc].sum+=(tree[rc].r-tree[rc].l+1)*add[o];
        add[lc]+=add[o];
        add[rc]+=add[o];
        add[o]=0;
        return;
    }
    
    inline void update(int o,int x,int y,int z)
    {
        int l=tree[o].l,r=tree[o].r;
        if(x<=l&&y>=r)
        {
            tree[o].sum+=(r-l+1)*z;
            add[o]+=z; 
        }
        else
        {
            if(x>r||y<l) return;
            else
            {
                int mid=tree[o].mid();
                if(add[o]) pushdown(o);
                update(lc,x,y,z);
                update(rc,x,y,z);
            }
                
        }    
    } 
    
    inline int query(int o,int x)
    {
        int l=tree[o].l,r=tree[o].r;
        if(l==r) return tree[o].sum;
        else
        {
            if(add[o]) pushdown(o);
            int mid=tree[o].mid();
            if(mid>=x) return query(lc,x); 
            else return query(rc,x);
        }
    }
    
    inline void change(int a,int b)
    {
        int ta=top[a],tb=top[b];
        while(ta!=tb)
        {
            if(dep[ta]<dep[tb]) swap(ta,tb),swap(a,b);
            update(1,num[ta],num[a],1);
            a=fa[ta];ta=top[a];
        }
        if(a==b) update(1,num[a],num[b],1);
        else
        {
            if(dep[a]<dep[b]) swap(a,b);
            update(1,num[b],num[a],1);
        }
    }
    
    int main()
    {
        n=read();
        for(int i=1;i<=n;i++)    a[i]=read(),head[i]=-1;
        for(int i=1;i<n;i++)
        {
            int x=read(),y=read();
            addedge(x,y);
            addedge(y,x);
        }
        fa[1]=0;dep[1]=1;
        dfs1(1,0);
        dfs2(1,1);
        build(1,1,h);
        update(1,num[a[1]],num[a[1]],1);    
    
        for(int i=2;i<=n;i++)
        {
            change(a[i-1],a[i]);
            update(1,num[a[i-1]],num[a[i-1]],-1);
        //    cout<<query(1,num[a[1]])<<endl;
        }
        update(1,num[a[n]],num[a[n]],-1);
        for(int i=1;i<=n;i++)
        {
            printf("%d
    ",query(1,num[i]));
        }
    }
  • 相关阅读:
    Oracle 获取创建控制文件的脚本
    ESXi下误删磁盘分区
    Oracle 3DES加密示例
    Oracle job 执行多个存储过程
    解开紧箍咒
    国际关系之美国南海战略意图(转)
    GHOST系统锁定主页常用软件及解决方案
    cut命令详解
    grep命令详解
    awk命令详解
  • 原文地址:https://www.cnblogs.com/wlzs1432/p/9370844.html
Copyright © 2020-2023  润新知