zoukankan      html  css  js  c++  java
  • 【uoj128】 NOI2015—软件包管理器

    http://uoj.ac/problem/128 (题目链接)

    题意

      给出一棵树,每个节点代表一个软件包,维护卸载和安装操作。若要卸载节点x,那么必须卸载它的子树上的所有软件包;若要安装节点x必须安装所有它的祖先。每次询问安装或卸载某个软件包一共需要安装或者卸载多少个软件包。

    Solution

      很裸的树链剖分,0表示未安装,1表示已安装。安装操作很好处理对吧,每次对节点x到根节点这条路径进行查询和修改即可。对于卸载操作,由于子树的dfs序是连续的,我们维护dfs序,进入x的子树时的时间戳L[x],退出时的时间戳R[x],查询和修改线段树上L[x]与R[x]之间的值即可。

      不知为何UOJ上数组要开大2倍才能过。。

    代码

    // uoj128
    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<cstdio>
    #include<cmath>
    #include<queue>
    #define MOD 1000000007
    #define inf 2147483640
    #define LL long long
    #define free(a) freopen(a".in","r",stdin);freopen(a".out","w",stdout);
    using namespace std;
    
    const int maxn=100010;
    struct tree {int l,r,s,tag;}tr[maxn<<1];
    struct edge {int to,next;}e[maxn<<1];
    int head[maxn],pos[maxn],size[maxn],deep[maxn],son[maxn],bl[maxn],bin[31],fa[maxn][31],L[maxn],R[maxn];
    int cnt,n,q,P;
    char s[maxn];
    
    void link(int u,int v) {
        e[++cnt].to=v;e[cnt].next=head[u];head[u]=cnt;
        e[++cnt].to=u;e[cnt].next=head[v];head[v]=cnt;
    }
    void build(int k,int s,int t) {
        tr[k]=(tree){s,t,0,-1};
        if (s==t) return;
        int mid=(s+t)>>1;
        build(k<<1,s,mid);
        build(k<<1|1,mid+1,t);
    }
    void pushdown(int k) {
        int v=tr[k].tag;
        tr[k<<1].s=v*(tr[k<<1].r-tr[k<<1].l+1);tr[k<<1].tag=v;
        tr[k<<1|1].s=v*(tr[k<<1|1].r-tr[k<<1|1].l+1);tr[k<<1|1].tag=v;
        tr[k].tag=-1;
    }
    void update(int k,int s,int t,int v) {
        int l=tr[k].l,r=tr[k].r;
        if (l==s && r==t) {tr[k].s=v*(r-l+1);tr[k].tag=v;return;}
        if (tr[k].tag!=-1) pushdown(k);
        int mid=(l+r)>>1;
        if (t<=mid) update(k<<1,s,t,v);
        else if (s>mid) update(k<<1|1,s,t,v);
        else update(k<<1,s,mid,v),update(k<<1|1,mid+1,t,v);
        tr[k].s=tr[k<<1].s+tr[k<<1|1].s;
    }
    int query(int k,int s,int t) {
        int l=tr[k].l,r=tr[k].r;
        if (l==s && r==t) return tr[k].s;
        if (tr[k].tag!=-1) pushdown(k);
        int mid=(l+r)>>1;
        if (t<=mid) return query(k<<1,s,t);
        else if (s>mid) return query(k<<1|1,s,t);
        else return query(k<<1,s,mid)+query(k<<1|1,mid+1,t);
    }
    void dfs1(int x) {
        size[x]=1;
        for (int i=head[x];i;i=e[i].next) if (e[i].to!=fa[x][0]) {
                deep[e[i].to]=deep[x]+1;
                fa[e[i].to][0]=x;
                dfs1(e[i].to);
                size[x]+=size[e[i].to];
                if (size[e[i].to]>size[son[x]] || son[x]==0) son[x]=e[i].to;
            }
    }
    void dfs2(int x,int top) {
        L[x]=pos[x]=++P;bl[x]=top;
        if (son[x]) dfs2(son[x],top);
        for (int i=head[x];i;i=e[i].next)
            if (e[i].to!=son[x] && e[i].to!=fa[x][0]) dfs2(e[i].to,e[i].to);
        R[x]=P;
    }
    int solve(int x,int f) {
        int s=0;
        while (bl[x]!=bl[f]) {
            s+=query(1,pos[bl[x]],pos[x]);
            update(1,pos[bl[x]],pos[x],1);
            x=fa[bl[x]][0];
        }
        if (pos[x]>=pos[f]) s+=query(1,pos[f],pos[x]),update(1,pos[f],pos[x],1);
        return s;
    }
    int main() {
        scanf("%d",&n);
        for (int x,i=1;i<n;i++) {
            scanf("%d",&x);
            link(i,x);
        }
        dfs1(0);
        dfs2(0,0);
        build(1,1,n);
        scanf("%d",&q);
        while (q--) {
            int x;
            scanf("%s%d",s,&x);
            if (s[0]=='i') {
                //int tmp=solve(x,0);
                printf("%d
    ",deep[x]+1-solve(x,0));
            }
            else {
                int tmp=query(1,L[x],R[x]);
                printf("%d
    ",tmp);
                update(1,L[x],R[x],0);
            }
        }
        return 0;
    }
    

      

      

    This passage is made by MashiroSky.
  • 相关阅读:
    java.lang.AbstractMethodError: com.microsoft.jdbc.base.BaseDatabaseMetaData.supportsGetGeneratedKeys()Z
    安装oracle后java -version命令显示 jdk version "1.3.1"的原因
    jquery 获取和设置Select选项常用方法总结
    select动态增加option
    Jquery detect page refresh
    HibernateTemplate 查询
    The dialect was not set. Set the property hibernate.dialect
    hibernate的异常 Session was already closed
    <c:forEach>取得集合数量
    Jstl标签<c:forEach>的用法
  • 原文地址:https://www.cnblogs.com/MashiroSky/p/5909627.html
Copyright © 2011-2022 走看看