zoukankan      html  css  js  c++  java
  • [JLOI2014]松鼠的新家

     
     

    3631: [JLOI2014]松鼠的新家

    Time Limit: 10 Sec  Memory Limit: 128 MB
    Submit: 2567  Solved: 1360

    Description

    松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n个房间,并且有n-1根树枝连接,每个房间都可以相互到达,且俩个房间之间的路线都是唯一的。天哪,他居然真的住在“树”上。松鼠想邀请小熊维尼前来参观,并且还指定一份参观指南,他希望维尼能够按照他的指南顺序,先去a1,再去a2,……,最后到an,去参观新家。
    可是这样会导致维尼重复走很多房间,懒惰的维尼不听地推辞。可是松鼠告诉他,每走到一个房间,他就可以从房间拿一块糖果吃。维尼是个馋家伙,立马就答应了。
    现在松鼠希望知道为了保证维尼有糖果吃,他需要在每一个房间各放至少多少个糖果。因为松鼠参观指南上的最后一个房间an是餐厅,餐厅里他准备了丰盛的大餐,所以当维尼在参观的最后到达餐厅时就不需要再拿糖果吃了。

    Input

    第一行一个整数n,表示房间个数
    第二行n个整数,依次描述a1-an
    接下来n-1行,每行两个整数x,y,表示标号x和y的两个房间之间有树枝相连。

    Output

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

    Sample Input

    5
    1 4 5 3 2
    1 2
    2 4
    2 3
    4 5

    Sample Output

    1
    2
    1
    2
    1

    HINT

    2<= n <=300000

    这道题一开始觉得很难很蛇皮一直没写,并且还自不量力的劝说肖明也不要写。。但是过了一会说,这题很水啊。你就树链剖分完了之后线段树区间加一下不就可以了么。。我觉得十分有道理。

    其实这题也真的就是这样,树链剖分完了之后,对于每相邻的两个数进行区间加的操作。对于重复的处理我们考虑使用数组记录,最后一并减去就可以了。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #include<queue>
    #define ll long long
    #define ls rt<<1
    #define rs rt<<1|1
    #define inf 50000000
    #define re register
    #define MAXN 500005
    using namespace std;
    struct po{
        int nxt,to;
    }; 
    po edge[MAXN<<1];
    int id[MAXN],f[MAXN],wson[MAXN],top[MAXN],size[MAXN],dep[MAXN];
    int sum[MAXN<<2],add[MAXN<<2];
    int head[MAXN],n,m,s,num,cnt;
    int a[MAXN],nm[MAXN];
    inline int read()
    {
        int x=0,c=1;
        char ch=' ';
        while((ch>'9'||ch<'0')&&ch!='-')ch=getchar();
        while(ch=='-')c*=-1,ch=getchar();
        while(ch<='9'&&ch>='0')x=x*10+ch-'0',ch=getchar();
        return x*c;
    }
    inline void add_edge(int from,int to)
    {
        edge[++num].nxt=head[from];edge[num].to=to;head[from]=num;
        edge[++num].nxt=head[to];edge[num].to=from;head[to]=num;
    }
    inline void dfs1(int u,int fa)
    {
        size[u]=1;f[u]=fa;dep[u]=dep[fa]+1;
        for(re int i=head[u];i;i=edge[i].nxt){
            int v=edge[i].to;
            if(v==fa) continue;
            dfs1(v,u);
            size[u]+=size[v];
            if(size[wson[u]]<size[v]) wson[u]=v;
        }
    }
    inline void dfs2(int u,int tp)
    {
        id[u]=++cnt;top[u]=tp;
        if(wson[u]) dfs2(wson[u],tp);
        for(re int i=head[u];i;i=edge[i].nxt){
            int v=edge[i].to;
            if(v==f[u]||v==wson[u]) continue;
            dfs2(v,v);
        }
    }
    inline void pushup(int rt)
    {
        sum[rt]=sum[ls]+sum[rs];
    }
    inline void pushdown(int l,int r,int rt)
    {
        int mid=l+r>>1;
        if(add[rt]){
            add[ls]+=add[rt];
            add[rs]+=add[rt];
            sum[ls]+=(mid-l+1)*add[rt];
            sum[rs]+=(r-mid)*add[rt];
            add[rt]=0;
        }
    }
    inline void update(int L,int R,int k,int l,int r,int rt)
    {
        if(L<=l&&r<=R){
            add[rt]+=k;
            sum[rt]+=(r-l+1)*k;
            return;
        }
        pushdown(l,r,rt);
        int mid=l+r>>1;
        if(L<=mid) update(L,R,k,l,mid,ls);
        if(R>mid) update(L,R,k,mid+1,r,rs);
        pushup(rt);
    }
    inline int query(int pos,int l,int r,int rt)
    {
        if(l==r) return sum[rt];
        pushdown(l,r,rt);
        int mid=l+r>>1;
        if(pos<=mid) return query(pos,l,mid,ls);
        else return query(pos,mid+1,r,rs);
    }
    inline void change(int x,int y,int k)
    {
        while(top[x]!=top[y]){
            if(dep[top[x]]<dep[top[y]]) swap(x,y);
            update(id[top[x]],id[x],k,1,n,1);
            x=f[top[x]];
        }
        if(dep[x]>dep[y]) swap(x,y);
        update(id[x],id[y],k,1,n,1);
    }
    int main()
    {
        n=read();
        for(re int i=1;i<=n;i++)
            a[i]=read();
        for(re int i=1;i<=n-1;i++){
            int x,y;
            x=read();y=read();
            add_edge(x,y);
        }
        
        dfs1(1,1);
        dfs2(1,1);
        for(re int i=1;i<n;i++){
            nm[a[i+1]]++;
            change(a[i],a[i+1],1);
        }
        for(re int i=1;i<=n;i++){
            printf("%d
    ",query(id[i],1,n,1)-nm[i]);
        }
    }
  • 相关阅读:
    bzoj 1017 魔兽地图DotR
    poj 1322 chocolate
    bzoj 1045 糖果传递
    poj 3067 japan
    timus 1109 Conference(二分图匹配)
    URAL 1205 By the Underground or by Foot?(SPFA)
    URAL 1242 Werewolf(DFS)
    timus 1033 Labyrinth(BFS)
    URAL 1208 Legendary Teams Contest(DFS)
    URAL 1930 Ivan's Car(BFS)
  • 原文地址:https://www.cnblogs.com/victorique/p/8669535.html
Copyright © 2011-2022 走看看