zoukankan      html  css  js  c++  java
  • 「NOI2015」「Codevs4621」软件包管理器(树链剖分

    4621 [NOI2015]软件包管理器

     

    时间限制: 1 s
    空间限制: 256000 KB
    题目等级 : 钻石 Diamond
     
    题目描述 Description

    Linux用户和OSX用户一定对软件包管理器不会陌生。通过软件包管理器,你可以通过一行命令安装某一个软件包,然后软件包管理器会帮助你从软件源下载软件包,同时自动解决所有的依赖(即下载安装这个软件包的安装所依赖的其它软件包),完成所有的配置。Debian/Ubuntu使用的apt-get,Fedora/CentOS使用的yum,以及OSX下可用的homebrew都是优秀的软件包管理器。

    你决定设计你自己的软件包管理器。不可避免地,你要解决软件包之间的依赖问题。如果软件包A依赖软件包B,那么安装软件包A以前,必须先安装软件包B。同时,如果想要卸载软件包B,则必须卸载软件包A。现在你已经获得了所有的软件包之间的依赖关系。而且,由于你之前的工作,除0号软件包以外,在你的管理器当中的软件包都会依赖一个且仅一个软件包,而0号软件包不依赖任何一个软件包。依赖关系不存在环(若有m(m≥2)个软件包A1,A2,A3,…,Am,其中A1依赖A2,A2依赖A3,A3依赖A4,……,Am−1依赖Am,而Am依赖A1,则称这m个软件包的依赖关系构成环),当然也不会有一个软件包依赖自己。

    现在你要为你的软件包管理器写一个依赖解决程序。根据反馈,用户希望在安装和卸载某个软件包时,快速地知道这个操作实际上会改变多少个软件包的安装状态(即安装操作会安装多少个未安装的软件包,或卸载操作会卸载多少个已安装的软件包),你的任务就是实现这个部分。注意,安装一个已安装的软件包,或卸载一个未安装的软件包,都不会改变任何软件包的安装状态,即在此情况下,改变安装状态的软件包数为0。

    输入描述 Input Description

    输入文件的第1行包含1个正整数n,表示软件包的总数。软件包从0开始编号。

    随后一行包含n−1个整数,相邻整数之间用单个空格隔开,分别表示1,2,3,…,n−2,n−1号软件包依赖的软件包的编号。

    接下来一行包含1个正整数q,表示询问的总数。

    之后q行,每行1个询问。询问分为两种:

    installx:表示安装软件包x

    uninstallx:表示卸载软件包x

    你需要维护每个软件包的安装状态,一开始所有的软件包都处于未安装状态。对于每个操作,你需要输出这步操作会改变多少个软件包的安装状态,随后应用这个操作(即改变你维护的安装状态)。

    输出描述 Output Description

    输出文件包括q行。

    输出文件的第i行输出1个整数,为第i步操作中改变安装状态的软件包数。

    样例输入 Sample Input

    7
    0 0 0 1 1 5
    5
    install 5
    install 6
    uninstall 1
    install 4
    uninstall 0

    样例输出 Sample Output

    3
    1
    3
    2
    3

    数据范围及提示 Data Size & Hint

    一开始所有的软件包都处于未安装状态。

    安装 5 号软件包,需要安装 0,1,5 三个软件包。

    之后安装 6 号软件包,只需要安装 6 号软件包。此时安装了 0,1,5,6 四个软件包。

    卸载 1 号软件包需要卸载 1,5,6 三个软件包。此时只有 0 号软件包还处于安装状态。

    之后安装 4 号软件包,需要安装 1,4 两个软件包。此时 0,1,4 处在安装状态。

    最后,卸载 0 号软件包会卸载所有的软件包。




    n=100000

    q=100000

    题解

    还是挺板子的啦。

    首先建树:每个点依赖的点作为它的父亲,可以建一棵以0为根的树。

    可以想到,对于安装操作,要求到根的路上有多少个未装,并且全部装好。

    对于卸载操作,要求子树内有多少个点已经安装了,并且全部删掉。

    然后剖一下,转换为线性。

    这样此题转化为:

    对于一个序列,我们要支持两种操作:

    安装:求区间内有多少个点为0,并将区间内每点变成1

    卸载:求区间内有多少个点为1,并将区间内每点变成0

    关于解决子问题的lazytag:

    laz=0表示无taglaz=1表示这个区间应该全为1laz=2表示这个区间应该全为0

    对线段树上任何一个点的值要操作之前 一定 一定 一定要pushtag啊!!!QAQ

    任 何 一 个 点!!!任何!!!QAQ

    然后就很板子了。

      1 /*
      2     qwerta
      3     P2146 [NOI2015]软件包管理器
      4     Accepted
      5     100
      6     代码 C++,3.2KB
      7     提交时间 2018-09-13 16:38:30
      8     耗时/内存
      9     6897ms, 16736KB
     10 */
     11 #include<cstdio>
     12 #include<iostream>
     13 using namespace std;
     14 #define R register
     15 const int MAXN=100000+7;
     16 struct emm{
     17     int f;
     18 }b[MAXN];
     19 int h[MAXN];
     20 int fa[MAXN];
     21 int s;
     22 int d[MAXN],siz[MAXN],top[MAXN],z[MAXN];
     23 void dfs(int x)
     24 {
     25     siz[x]=1;top[x]=x;
     26     int mac=-1,macc=-1;
     27     for(R int i=h[x];i;i=b[i].f)
     28     {
     29         d[i]=d[x]+1;
     30         dfs(i);
     31         siz[x]+=siz[i];
     32         if(macc<siz[i]){mac=i,macc=siz[i];}
     33     }
     34     if(mac!=-1)
     35     {
     36         z[x]=mac;
     37         top[mac]=x;
     38     }
     39     return;
     40 }
     41 int q[MAXN],dfn[MAXN];
     42 int tot=0;
     43 void dfss(int x)
     44 {
     45     q[++tot]=x;
     46     dfn[x]=tot;
     47     if(z[x])dfss(z[x]);
     48     for(R int i=h[x];i;i=b[i].f)
     49     if(i!=z[x])
     50     dfss(i);
     51     return;
     52 }
     53 int fitop(int x)
     54 {
     55     if(top[x]==x)return x;
     56     return top[x]=fitop(top[x]);
     57 }
     58 struct ahh{
     59     int l,r,mid,v,laz;
     60 }a[16*MAXN];
     61 #define lz (i<<1)
     62 #define rz ((i<<1)|1)
     63 #define md a[i].mid
     64 void build(int i,int ll,int rr)
     65 {
     66     a[i].l=ll;
     67     a[i].r=rr;
     68     if(ll==rr)return;
     69     md=(ll+rr)>>1;
     70     build(lz,ll,md);
     71     build(rz,md+1,rr);
     72     return;
     73 }
     74 void pushtag(int i)
     75 {
     76     if(a[i].laz==0)return;
     77     if(a[i].laz==1)
     78     {
     79         a[lz].laz=1;
     80         a[rz].laz=1;
     81         a[i].v=a[i].r-a[i].l+1;
     82         a[i].laz=0;
     83         return;
     84     }
     85     else
     86     {
     87         a[lz].laz=2;
     88         a[rz].laz=2;
     89         a[i].v=0;
     90         a[i].laz=0;
     91     }
     92 }
     93 int ans;
     94 void add(int i,int ll,int rr)
     95 {
     96     pushtag(i);
     97     if(a[i].l==ll&&a[i].r==rr)
     98     {ans+=(a[i].r-a[i].l+1)-a[i].v;a[i].v=a[i].r-a[i].l+1;a[lz].laz=a[rz].laz=1;return;}
     99     if(rr<=md){add(lz,ll,rr);pushtag(rz);}
    100     else if(md+1<=ll){add(rz,ll,rr);pushtag(lz);}
    101     else {add(lz,ll,md);add(rz,md+1,rr);}
    102     a[i].v=a[lz].v+a[rz].v;
    103     return;
    104 }
    105 void mins(int i,int ll,int rr)
    106 {
    107     pushtag(i);
    108     if(a[i].l==ll&&a[i].r==rr){ans+=a[i].v;a[i].v=0;a[lz].laz=a[rz].laz=2;return;}
    109     if(rr<=md){mins(lz,ll,rr);pushtag(rz);}
    110     else if(md+1<=ll){mins(rz,ll,rr);pushtag(lz);}
    111     else {mins(lz,ll,md);mins(rz,md+1,rr);}
    112     a[i].v=a[lz].v+a[rz].v;
    113     return;
    114 }
    115 char st[27];
    116 int main()
    117 {
    118     //freopen("a.in","r",stdin);
    119     ios::sync_with_stdio(false);
    120     cin.tie(NULL),cout.tie(NULL);
    121     int n;
    122     cin>>n;
    123     for(R int i=1;i<n;++i)
    124     {
    125         cin>>fa[i];
    126         b[i].f=h[fa[i]];
    127         h[fa[i]]=i;
    128     }
    129     s=0;
    130     d[s]=1;
    131     fa[s]=-1;
    132     dfs(s);
    133     tot=-1;
    134     dfss(s);
    135     for(R int i=0;i<n;++i)
    136     top[i]=fitop(i);
    137     build(1,0,n-1);
    138     int qs;
    139     cin>>qs;
    140     for(R int i=1;i<=qs;++i)
    141     {
    142         cin>>st;
    143         if(st[0]=='i')
    144         {
    145             int x;
    146             cin>>x;
    147             ans=0;
    148             while(x!=-1)
    149             {
    150                 add(1,dfn[top[x]],dfn[x]);
    151                 x=fa[top[x]];
    152             }
    153             cout<<ans<<endl;
    154         }
    155         else
    156         {
    157             int x;
    158             cin>>x;
    159             ans=0;
    160             mins(1,dfn[x],dfn[x]+siz[x]-1);
    161         }
    162     }
    163     return 0;
    164 }

    最后吐槽一下自己(没有关同步流和加register之前)巨大的常数

    在TLE的边缘试探(逃

  • 相关阅读:
    书签
    jQueryUI Plugin TableSorter的2个widget扩展
    CSS之关于clearfix--清除浮动
    C#中的is关键字原来会做null检查
    jQuery UI 控件之Slider
    延长Nodejs HTTP 的连接时长
    Nodejs的Promise库
    jQuery的选择器中的通配符
    SharePoint Server 2010 中的基本任务
    ajax浅析---ScriptManagerProxy
  • 原文地址:https://www.cnblogs.com/qwerta/p/9641725.html
Copyright © 2011-2022 走看看