zoukankan      html  css  js  c++  java
  • 【树链剖分(区间线段树)】BZOJ4196-[NOI2015]软件包管理

    【题目大意】

    如果软件包A依赖软件包B,那么安装软件包A以前,必须先安装软件包B。同时,如果想要卸载软件包B,则必须卸载软件包A。而且,由于你之前的工作,除0号软件包以外,在你的管理器当中的软件包都会依赖一个且仅一个软件包,而0号软件包不依赖任何一个软件包。依赖关系不存在环。求出在安装和卸载某个软件包时,实际上会改变多少个软件包的安装状态(即安装操作会安装多少个未安装的软件包,或卸载操作会卸载多少个已安装的软件包。(注意,安装一个已安装的软件包,或卸载一个未安装的软件包,都不会改变任何软件包的安装状态,即在此情况下,改变安装状态的软件包数为0)

    【思路】

    裸的树剖...然而我发现我写错了区间覆盖的线段树,要设置两个标记,一个记录该区间是否需要修改,另一个记录该区间覆盖的值。

    话说BZOJ要用printf否则会RE,我怎么不长记性呢………

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<algorithm>
      5 #include<vector>
      6 #define lson l,m,rt<<1
      7 #define rson m+1,r,rt<<1|1
      8 using namespace std;
      9 const int MAXN=100000+50;
     10 const int rt=0;
     11 vector<int> E[MAXN];
     12 int n;
     13 int fa[MAXN],dep[MAXN],hson[MAXN],size[MAXN];
     14 int cnt=0,top[MAXN],pos[MAXN];
     15 int sum[MAXN<<3],add[MAXN<<3],change[MAXN<<3];
     16 
     17 //树链剖分部分 
     18 void addedge(int u,int v)
     19 {
     20     E[u].push_back(v);
     21 }
     22 
     23 void dfs1(int u,int father,int depth)
     24 {
     25     fa[u]=father;
     26     dep[u]=depth;
     27     size[u]=1;
     28     hson[u]=-1;
     29     for (int i=0;i<E[u].size();i++)
     30     {
     31         int to=E[u][i];
     32         dfs1(to,u,depth+1);
     33         size[u]+=size[to];
     34         if (hson[u]==-1 || size[to]>size[hson[u]]) hson[u]=to;
     35     }
     36 }
     37 
     38 void dfs2(int u,int t)
     39 {
     40     pos[u]=++cnt;
     41     top[u]=t;
     42     if (hson[u]!=-1) dfs2(hson[u],t);
     43     for (int i=0;i<E[u].size();i++)
     44     {
     45         int to=E[u][i];
     46         if (to!=hson[u]) dfs2(to,to);
     47     }
     48 }
     49 
     50 //线段树部分
     51 void build()
     52 {
     53     memset(sum,0,sizeof(sum));
     54     memset(add,0,sizeof(add));
     55 } 
     56 
     57 void pushup(int rt)
     58 {
     59     sum[rt]=sum[rt<<1]+sum[rt<<1|1];
     60 }
     61 
     62 void pushdown(int rt,int m)
     63 {
     64     if (change[rt])
     65     {
     66         change[rt<<1]=change[rt<<1|1]=1;
     67         add[rt<<1]=add[rt];
     68         add[rt<<1|1]=add[rt];
     69         sum[rt<<1]=add[rt]*(m-(m>>1));
     70         sum[rt<<1|1]=add[rt]*(m>>1);
     71         add[rt]=change[rt]=0;
     72     }
     73 } 
     74 
     75 int query_sum(int L,int R,int l,int r,int rt)
     76 {
     77     if (L<=l && r<=R) return sum[rt];
     78     pushdown(rt,r-l+1);
     79     int m=(l+r)>>1;
     80     int ret=0;
     81     if (m>=L) ret+=query_sum(L,R,lson);
     82     if (m<R) ret+=query_sum(L,R,rson);
     83     pushup(rt); 
     84     return ret;
     85 }
     86 
     87 void modify(int L,int R,int l,int r,int rt,int x)
     88 {
     89     if (L<=l && r<=R)
     90     {
     91         change[rt]=1;
     92         add[rt]=x;
     93         sum[rt]=(r-l+1)*x;
     94         return;
     95     }
     96     pushdown(rt,r-l+1);
     97     int m=(l+r)>>1;
     98     if (m>=L) modify(L,R,lson,x);
     99     if (m<R) modify(L,R,rson,x);
    100     pushup(rt);
    101 }
    102 
    103 //树链剖分查询部分 
    104 int install(int x,int y)
    105 {
    106     int ret=dep[x],f1=top[x],f2=top[y];
    107     while (f1!=f2)
    108     {
    109         ret-=query_sum(pos[f1],pos[x],1,n,1);
    110         modify(pos[f1],pos[x],1,n,1,1);
    111         x=fa[f1];
    112         f1=top[x];
    113     }
    114     ret-=query_sum(pos[y],pos[x],1,n,1);
    115     modify(pos[y],pos[x],1,n,1,1);
    116     return (ret);
    117 }
    118 
    119 int uninstall(int x)
    120 {
    121     int ret=query_sum(pos[x],pos[x]+size[x]-1,1,n,1);
    122     modify(pos[x],pos[x]+size[x]-1,1,n,1,0);
    123     return ret;
    124 }
    125 
    126 
    127 //读入部分 
    128 void init()
    129 {
    130     scanf("%d",&n);
    131     for (int i=1;i<n;i++)
    132     {
    133         int tmp;
    134         scanf("%d",&tmp);
    135         addedge(tmp,i);
    136     }
    137     dfs1(0,0,1);
    138     dfs2(0,0);
    139 }
    140 
    141 void get_ans()
    142 {
    143     memset(sum,0,sizeof(sum));
    144     memset(change,0,sizeof(change));
    145     memset(add,0,sizeof(add));
    146     int q;
    147     scanf("%d",&q);
    148     for (int i=0;i<q;i++)
    149     {
    150         char str[25];
    151         int x;
    152         scanf("%s%d",str,&x);
    153         if (str[0]=='i') printf("%d
    ",install(x,rt));
    154             else if (str[0]=='u') printf("%d
    ",uninstall(x));
    155     }
    156 }
    157 
    158 int main()
    159 {
    160     init();
    161     build(); 
    162     get_ans();
    163     return 0;
    164 }
  • 相关阅读:
    浏览器图片渲染优化教程
    C#把 DataTable转换为Model实体
    .NET静态变量与静态方法并发的问题
    三种方法查看MySQL数据库的版本
    Mysql 存储引擎 InnoDB与Myisam的主要区别
    dotnet core 出现Can not find runtime target for framework '.NETCoreApp,Version=v1.6' 的解决办法
    细说 C# 中的 IEnumerable和IEnumerator接口
    ASP.NET CORE dotnet run 命令使用debug方式运行
    安装了插件情况下 强制开启火狐浏览器的多进程功能
    JSON 字符串中的中括号和大括号区别详解
  • 原文地址:https://www.cnblogs.com/iiyiyi/p/5655178.html
Copyright © 2011-2022 走看看