【树链剖分(区间线段树)】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\n",install(x,rt));
154             else if (str[0]=='u') printf("%d\n",uninstall(x));
155     }
156 }
157 
158 int main()
159 {
160     init();
161     build(); 
162     get_ans();
163     return 0;
164 }

 

posted @ 2016-07-09 08:58  iiyiyi  阅读(211)  评论(0编辑  收藏  举报