【树链剖分(区间线段树)】BZOJ4196-[NOI2015]软件包管理
【题目大意】
如果软件包A依赖软件包B,那么安装软件包A以前,必须先安装软件包B。同时,如果想要卸载软件包B,则必须卸载软件包A。而且,由于你之前的工作,除0号软件包以外,在你的管理器当中的软件包都会依赖一个且仅一个软件包,而0号软件包不依赖任何一个软件包。依赖关系不存在环。求出在安装和卸载某个软件包时,实际上会改变多少个软件包的安装状态(即安装操作会安装多少个未安装的软件包,或卸载操作会卸载多少个已安装的软件包。(注意,安装一个已安装的软件包,或卸载一个未安装的软件包,都不会改变任何软件包的安装状态,即在此情况下,改变安装状态的软件包数为0)
【思路】
裸的树剖...然而我发现我写错了区间覆盖的线段树,要设置两个标记,一个记录该区间是否需要修改,另一个记录该区间覆盖的值。
话说BZOJ要用printf否则会RE,我怎么不长记性呢………
- #include<iostream>
- #include<cstdio>
- #include<cstring>
- #include<algorithm>
- #include<vector>
- #define lson l,m,rt<<1
- #define rson m+1,r,rt<<1|1
- using namespace std;
- const int MAXN=+;
- const int rt=;
- vector<int> E[MAXN];
- int n;
- int fa[MAXN],dep[MAXN],hson[MAXN],size[MAXN];
- int cnt=,top[MAXN],pos[MAXN];
- int sum[MAXN<<],add[MAXN<<],change[MAXN<<];
- //树链剖分部分
- void addedge(int u,int v)
- {
- E[u].push_back(v);
- }
- void dfs1(int u,int father,int depth)
- {
- fa[u]=father;
- dep[u]=depth;
- size[u]=;
- hson[u]=-;
- for (int i=;i<E[u].size();i++)
- {
- int to=E[u][i];
- dfs1(to,u,depth+);
- size[u]+=size[to];
- if (hson[u]==- || size[to]>size[hson[u]]) hson[u]=to;
- }
- }
- void dfs2(int u,int t)
- {
- pos[u]=++cnt;
- top[u]=t;
- if (hson[u]!=-) dfs2(hson[u],t);
- for (int i=;i<E[u].size();i++)
- {
- int to=E[u][i];
- if (to!=hson[u]) dfs2(to,to);
- }
- }
- //线段树部分
- void build()
- {
- memset(sum,,sizeof(sum));
- memset(add,,sizeof(add));
- }
- void pushup(int rt)
- {
- sum[rt]=sum[rt<<]+sum[rt<<|];
- }
- void pushdown(int rt,int m)
- {
- if (change[rt])
- {
- change[rt<<]=change[rt<<|]=;
- add[rt<<]=add[rt];
- add[rt<<|]=add[rt];
- sum[rt<<]=add[rt]*(m-(m>>));
- sum[rt<<|]=add[rt]*(m>>);
- add[rt]=change[rt]=;
- }
- }
- int query_sum(int L,int R,int l,int r,int rt)
- {
- if (L<=l && r<=R) return sum[rt];
- pushdown(rt,r-l+);
- int m=(l+r)>>;
- int ret=;
- if (m>=L) ret+=query_sum(L,R,lson);
- if (m<R) ret+=query_sum(L,R,rson);
- pushup(rt);
- return ret;
- }
- void modify(int L,int R,int l,int r,int rt,int x)
- {
- if (L<=l && r<=R)
- {
- change[rt]=;
- add[rt]=x;
- sum[rt]=(r-l+)*x;
- return;
- }
- pushdown(rt,r-l+);
- int m=(l+r)>>;
- if (m>=L) modify(L,R,lson,x);
- if (m<R) modify(L,R,rson,x);
- pushup(rt);
- }
- //树链剖分查询部分
- int install(int x,int y)
- {
- int ret=dep[x],f1=top[x],f2=top[y];
- while (f1!=f2)
- {
- ret-=query_sum(pos[f1],pos[x],,n,);
- modify(pos[f1],pos[x],,n,,);
- x=fa[f1];
- f1=top[x];
- }
- ret-=query_sum(pos[y],pos[x],,n,);
- modify(pos[y],pos[x],,n,,);
- return (ret);
- }
- int uninstall(int x)
- {
- int ret=query_sum(pos[x],pos[x]+size[x]-,,n,);
- modify(pos[x],pos[x]+size[x]-,,n,,);
- return ret;
- }
- //读入部分
- void init()
- {
- scanf("%d",&n);
- for (int i=;i<n;i++)
- {
- int tmp;
- scanf("%d",&tmp);
- addedge(tmp,i);
- }
- dfs1(,,);
- dfs2(,);
- }
- void get_ans()
- {
- memset(sum,,sizeof(sum));
- memset(change,,sizeof(change));
- memset(add,,sizeof(add));
- int q;
- scanf("%d",&q);
- for (int i=;i<q;i++)
- {
- char str[];
- int x;
- scanf("%s%d",str,&x);
- if (str[]=='i') printf("%d\n",install(x,rt));
- else if (str[]=='u') printf("%d\n",uninstall(x));
- }
- }
- int main()
- {
- init();
- build();
- get_ans();
- return ;
- }
【树链剖分(区间线段树)】BZOJ4196-[NOI2015]软件包管理的更多相关文章
- [bzoj4196][Noi2015]软件包管理器_树链剖分_线段树
软件包管理器 bzoj-4196 Noi-2015 题目大意:Linux用户和OSX用户一定对软件包管理器不会陌生.通过软件包管理器,你可以通过一行命令安装某一个软件包,然后软件包管理器会帮助你从软件 ...
- bzoj 4034 [HAOI2015] T2(树链剖分,线段树)
4034: [HAOI2015]T2 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 1536 Solved: 508[Submit][Status] ...
- bzoj 3626 [LNOI2014]LCA(离线处理+树链剖分,线段树)
3626: [LNOI2014]LCA Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 1272 Solved: 451[Submit][Status ...
- 【BZOJ3531】旅行(树链剖分,线段树)
[BZOJ3531]旅行(树链剖分,线段树) 题面 Description S国有N个城市,编号从1到N.城市间用N-1条双向道路连接,满足 从一个城市出发可以到达其它所有城市.每个城市信仰不同的宗教 ...
- bzoj 1036 [ZJOI2008]树的统计Count(树链剖分,线段树)
1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 10677 Solved: 4313[Submit ...
- poj 3237 Tree(树链剖分,线段树)
Tree Time Limit: 5000MS Memory Limit: 131072K Total Submissions: 7268 Accepted: 1969 Description ...
- bzoj 2243 [SDOI2011]染色(树链剖分,线段树)
2243: [SDOI2011]染色 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 4637 Solved: 1726[Submit][Status ...
- HDU 4366 Successor(树链剖分+zkw线段树+扫描线)
[题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=4366 [题目大意] 有一个公司,每个员工都有一个上司,所有的人呈树状关系,现在给出每个人的忠诚值和 ...
- 【BZOJ5507】[GXOI/GZOI2019]旧词(树链剖分,线段树)
[BZOJ5507][GXOI/GZOI2019]旧词(树链剖分,线段树) 题面 BZOJ 洛谷 题解 如果\(k=1\)就是链并裸题了... 其实\(k>1\)发现还是可以用类似链并的思想,这 ...
- 【洛谷5439】【XR-2】永恒(树链剖分,线段树)
[洛谷5439][XR-2]永恒(树链剖分,线段树) 题面 洛谷 题解 首先两个点的\(LCP\)就是\(Trie\)树上的\(LCA\)的深度. 考虑一对点的贡献,如果这两个点不具有祖先关系,那么这 ...
随机推荐
- [洛谷P2073] 送花
送花 题目背景 小明准备给小红送一束花,以表达他对小红的爱意.他在花店看中了一些花,准备用它们包成花束. 题目描述 这些花都很漂亮,每朵花有一个美丽值W,价格为C. 小明一开始有一个空的花束,他不断地 ...
- 小K的农场
小K的农场 题目描述 小K在MC里面建立很多很多的农场,总共n个,以至于他自己都忘记了每个农场中种植作物的具体数量了,他只记得一些含糊的信息(共m个),以下列三种形式描述: 农场a比农场b至少多种植了 ...
- php 计算两个日期的间隔天数
使用php内部自带函数实现 1.使用DateTime::diff 实现计算 参考阅读>>PHP DateTime::diff() 上代码: <?php $start = " ...
- java使用JNA调用dll
1.自己搞一个dll出来.参考下面链接 http://blog.csdn.net/lqena/article/details/46357165. 2.下载jar jna-4.2.1.jar. 3.复制 ...
- 九大排序算法Java实现
之前学习数据结构与算法时花了三天时间整理九大排序算法,并采用Java语言来实现,今天第一次写博客,刚好可以把这些东西从总结的文档中拿出来与大家分享一下,同时作为自己以后的备忘录. 1.排序算法时间复杂 ...
- BZOJ 3994: [SDOI2015]约数个数和
3994: [SDOI2015]约数个数和 Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 898 Solved: 619[Submit][Statu ...
- 【洛谷 P3834】 可持久化线段树1(主席树)
题目链接 主席树=可持久化权值线段树. 如果你不会可持久化线段树,请右转 如果你不会权值线段树,请自行脑补,就是线段树维护值域里有多少个数出现. 可持久化线段树是支持查询历史版本的. 我们对每个数都进 ...
- [bzoj2002][Hnoi2010]Bounce弹飞绵羊——分块
Brief description 某天,Lostmonkey发明了一种超级弹力装置,为了在他的绵羊朋友面前显摆,他邀请小绵羊一起玩个游戏.游戏一开始,Lostmonkey在地上沿着一条直线摆上n个装 ...
- AtCoder Regular Contest 092 C D E F
C - 2D Plane 2N Points 题意 二维平面上有\(N\)个红点,\(N\)个蓝点,一个红点和一个蓝点能配成一对当且仅当\(x_r<x_b\)且\(y_r<y_b\). 问 ...
- LBP简单实现
Local Binary Pattern 确实够简单...先写个代码在这儿,空了再弄 #include <opencv2/opencv.hpp> #include <iostream ...