• 洛谷 2146 [NOI2015]软件包管理器


    【题解】

      每个软件只依赖另一个软件,且依赖关系不构成环,那么很容易想到这是树形结构。

      我们用1表示以安装,用0表示未安装或已卸载;那么安装一个软件,就是把它到树根的路径上所有的点都改为1;卸载一个软件,就是把它的子树全部改为0.

      状态改变的软件包数就是操作前后整棵树的点权和。

      这样我们直接树链剖分即可。

     1 #include<cstdio>
     2 #include<algorithm>
     3 #include<cstring>
     4 #include<vector>
     5 #define LL long long
     6 #define rg register
     7 #define N 100010
     8 #define ls (u<<1)
     9 #define rs (u<<1|1)
    10 #define mid ((a[u].l+a[u].r)>>1)
    11 #define len(x) (a[x].r-a[x].l+1)
    12 using namespace std;
    13 int n,m,cnt,last,fa[N],hvy[N],top[N],dep[N],siz[N],dfn[N];
    14 vector<int>son[N];
    15 struct tree{
    16     int l,r,sum; bool mark;
    17 }a[N<<2];
    18 inline int read(){
    19     int k=0,f=1; char c=getchar();
    20     while(c<'0'||c>'9')c=='-'&&(f=-1),c=getchar();
    21     while('0'<=c&&c<='9')k=k*10+c-'0',c=getchar();
    22     return k*f;
    23 }
    24 void dfs1(int x){
    25     siz[x]=1;
    26     for(rg int i=0,to;i<son[x].size();i++){
    27         dfs1(to=son[x][i]); siz[x]+=siz[to];
    28         if(siz[to]>siz[hvy[x]]) hvy[x]=to;
    29     }
    30 }
    31 void dfs2(int x,int tp){
    32     top[x]=tp; dfn[x]=++cnt;
    33     if(hvy[x]) dfs2(hvy[x],tp);
    34     for(rg int i=0,to;i<son[x].size();i++)
    35         if((to=son[x][i])!=hvy[x]) dfs2(to,to);
    36 }
    37 void build(int u,int l,int r){
    38     a[u].l=l; a[u].r=r;
    39     if(l<r) build(ls,l,mid),build(rs,mid+1,r);
    40 }
    41 inline void pushdown(int u){
    42     a[u].mark=0; a[ls].mark=a[rs].mark=1;
    43     if(a[u].sum) a[ls].sum=len(ls),a[rs].sum=len(rs);
    44     else a[ls].sum=a[rs].sum=0;
    45 }
    46 void update(int u,int l,int r,bool type){//type==1-->install
    47     if(l<=a[u].l&&a[u].r<=r){
    48         a[u].sum=type?len(u):0;
    49         a[u].mark=1;
    50         return;
    51     }
    52     if(a[u].mark) pushdown(u);
    53     if(l<=mid) update(ls,l,r,type);
    54     if(r>mid) update(rs,l,r,type);
    55     a[u].sum=a[ls].sum+a[rs].sum;
    56 }
    57 //int query(int u,int l,int r){
    58 //    if(l<=a[u].l&&a[u].r<=r) return a[u].sum;
    59 //    if(a[u].mark) pushdown(u); int ret=0;
    60 //    if(l<=mid) ret=query(ls,l,r);
    61 //    if(r>mid) ret+=query(rs,l,r);
    62 //    return ret;
    63 //}
    64 int main(){
    65     n=read();
    66     for(rg int i=2;i<=n;i++){
    67         int f=read()+1;
    68         fa[i]=f; dep[i]=dep[f]+1;
    69         son[f].push_back(i);
    70     }
    71     dfs1(1); dfs2(1,1); build(1,1,n);
    72 //    for(rg int i=1;i<=n;i++) printf("%d ",siz[i]); puts("siz");
    73     m=read();
    74     while(m--){
    75         char c=getchar(); while(c!='i'&&c!='u') c=getchar();
    76         int x=read()+1;
    77         if(c=='i'){
    78             int t=top[x];
    79             while(x){
    80                 update(1,dfn[t],dfn[x],1);
    81                 x=fa[t]; t=top[x];
    82             }
    83         }
    84         else update(1,dfn[x],dfn[x]+siz[x]-1,0);
    85         printf("%d
    ",abs(a[1].sum-last),a[1].sum); last=a[1].sum;
    86     }
    87     return 0;
    88 }
    View Code
  • 相关阅读:
    Java 中的 TreeSet
    自定义全局异常处理器(Java)
    GitHub Open Feign 使用总结
    搭建 Maven 仓库
    MySQL 的 SQL 笔记
    一道算法题:查找数组 arr 中第 k 小的奇数
    Java 的参数传递
    接口限流的几种算法
    Java 实现一个自定义分布式 Session
    函数反汇编
  • 原文地址:https://www.cnblogs.com/DriverLao/p/9381085.html
Copyright © 2020-2023  润新知