BZOJ4196: [Noi2015]软件包管理器(树链剖分)

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

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

随后一行包含n−1个整数,相邻整数之间用单个空格隔开,分别表示1,2,3,…,n−2,n−1号软件包依赖的软件包的编号。
接下来一行包含1个正整数q,表示询问的总数。
之后q行,每行1个询问。询问分为两种:
installx:表示安装软件包x
uninstallx:表示卸载软件包x
你需要维护每个软件包的安装状态,一开始所有的软件包都处于未安装状态。对于每个操作,你需要输出这步操作会改变多少个软件包的安装状态,随后应用这个操作(即改变你维护的安装状态)。

Output

输出文件包括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

解题思路:

显然这是一棵树。

支持询问到根节点有多少点被标记,清空子树标记。

一颗线段树,支持区间改为1/0。

维护树链剖分序即可。

然而被卡常,开了O2才过,好蒟蒻啊QAQ

代码:

  1 #pragma GCC optimize(2)
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 #define lll spc<<1
  6 #define rrr spc<<1|1
  7 inline int read()
  8 {
  9     int l=1;
 10     int ret=0;
 11     char ch=getchar();
 12     while(ch<'0'||ch>'9')
 13     {
 14         if(ch=='-')
 15             l=-l;
 16         ch=getchar();
 17     }
 18     while(ch<='9'&&ch>='0')
 19     {
 20         ret=ret*10+ch-'0';
 21         ch=getchar();
 22     }
 23     return ret*l;
 24 }
 25 struct trnt{
 26     int val;
 27     int len;
 28     int lzt;
 29     bool chg;
 30 }tr[1000000];
 31 struct pnt{
 32     int hd;
 33     int fa;
 34     int dp;
 35     int tp;
 36     int ind;
 37     int mxs;
 38     int wgt;
 39 }p[1000000];
 40 struct ent{
 41     int twd;
 42     int lst;
 43 }e[1000000];
 44 int cnt;
 45 int n,m;
 46 int dfn;
 47 char cmd[100];
 48 void ade(int f,int t)
 49 {
 50     cnt++;
 51     e[cnt].twd=t;
 52     e[cnt].lst=p[f].hd;
 53     p[f].hd=cnt;
 54 }
 55 void pushup(int spc)
 56 {
 57     tr[spc].val=tr[lll].val+tr[rrr].val;
 58     tr[spc].len=tr[lll].len+tr[rrr].len;
 59     return ;
 60 }
 61 void Add(int spc,int x)
 62 {
 63     tr[spc].val=tr[spc].len*x;
 64     tr[spc].lzt=x;
 65     tr[spc].chg=1;
 66     return ;
 67 }
 68 void pushdown(int spc)
 69 {
 70     if(tr[spc].chg)
 71     {
 72         Add(lll,tr[spc].lzt);
 73         Add(rrr,tr[spc].lzt);
 74         tr[spc].chg=0;
 75     }
 76     return ;
 77 }
 78 void build(int l,int r,int spc)
 79 {
 80     if(l==r)
 81     {
 82         tr[spc].len=1;
 83         return ;
 84     }
 85     int mid=(l+r)>>1;
 86     build(l,mid,lll);
 87     build(mid+1,r,rrr);
 88     pushup(spc);
 89     return ;
 90 }
 91 void update(int l,int r,int ll,int rr,int spc,int v)
 92 {
 93     if(l>rr||ll>r)
 94         return ;
 95     if(ll<=l&&r<=rr)
 96     {
 97         Add(spc,v);
 98         return ;
 99     }
100     pushdown(spc);
101     int mid=(l+r)>>1;
102     update(l,mid,ll,rr,lll,v);
103     update(mid+1,r,ll,rr,rrr,v);
104     pushup(spc);
105     return ;
106 }
107 int query(int l,int r,int ll,int rr,int spc)
108 {
109     if(ll>r||l>rr)
110         return 0;
111     if(ll<=l&&r<=rr)
112         return tr[spc].val;
113     pushdown(spc);
114     int mid=(l+r)>>1;
115     return query(l,mid,ll,rr,lll)+query(mid+1,r,ll,rr,rrr);
116 }
117 void Basic_dfs(int x,int f)
118 {
119     p[x].fa=f;
120     p[x].dp=p[f].dp+1;
121     p[x].wgt=1;
122     int maxs=-1;
123     for(int i=p[x].hd;i;i=e[i].lst)
124     {
125         int to=e[i].twd;
126         if(to==f)
127             continue;
128         Basic_dfs(to,x);
129         p[x].wgt+=p[to].wgt;
130         if(maxs<p[to].wgt)
131         {
132             maxs=p[to].wgt;
133             p[x].mxs=to;
134         }
135     }
136     return ;
137 }
138 void Build_dfs(int x,int top)
139 {
140     if(!x)
141         return ;
142     p[x].ind=++dfn;
143     p[x].tp=top;
144     Build_dfs(p[x].mxs,top);
145     for(int i=p[x].hd;i;i=e[i].lst)
146     {
147         int to=e[i].twd;
148         if(p[to].ind)
149             continue;
150         Build_dfs(to,to);
151     }
152 }
153 int Install(int x)
154 {
155     int ans=0;
156     while(p[x].tp!=1)
157     {
158         ans+=p[x].dp-p[p[x].tp].dp-query(1,dfn,p[p[x].tp].ind,p[x].ind,1)+1;
159         update(1,dfn,p[p[x].tp].ind,p[x].ind,1,1);
160         x=p[p[x].tp].fa;
161     }
162     ans+=p[x].dp-query(1,dfn,p[1].ind,p[x].ind,1);
163     update(1,dfn,p[1].ind,p[x].ind,1,1);
164     return ans;
165 }
166 int Uninstall(int x)
167 {
168     int ans=query(1,dfn,p[x].ind,p[x].ind+p[x].wgt-1,1);
169     update(1,dfn,p[x].ind,p[x].ind+p[x].wgt-1,1,0);
170     return ans;
171 }
172 int main()
173 {
174     n=read();
175     for(int i=2;i<=n;i++)
176     {
177         int x=read();
178         x++;
179         ade(x,i);
180         ade(i,x);
181     }
182     dfn=0;
183     Basic_dfs(1,1);
184     Build_dfs(1,1);
185     build(1,dfn,1);
186     m=read();
187     while(m--)
188     {
189         scanf("%s",cmd+1);
190         int x=read();
191         x++;
192         if(cmd[1]=='i')
193             printf("%d\n",Install(x));
194         else
195             printf("%d\n",Uninstall(x));
196     }
197     return 0;
198 }

 

posted @ 2018-09-28 23:22  Unstoppable728  阅读(231)  评论(0编辑  收藏  举报