NOI2015 软件包管理器 树剖+线段树
2015-12-11 17:05
399 查看
题目背景是一个安装与卸载软件的系统,软件之间关系是一棵树,以0为根节点。当你安装一个软件时需要先安装它的所有祖先,卸载时则要先卸载整个子树。对每一次操作询问改变状态的软件数目。
思路:dfs序做树剖,用线段树维护数据。
思路:dfs序做树剖,用线段树维护数据。
#include<iostream> #include<vector> #include<stdio.h> #define ls (id*2) #define rs (id*2+1) using namespace std; vector<int> lin[100005]; int in[100005],size[100005],fa[100005],top[100005],n,num,ans; struct node { int val; int lazy; }t[100005*4]; int abs(int a) { return a>=0?a:-a; } void push_down(int id,int l,int mid,int r) { if (t[id].lazy==-1)return; t[ls].lazy=t[id].lazy; t[rs].lazy=t[id].lazy; t[ls].val=(mid-l+1)*t[id].lazy; t[rs].val=(r-mid)*t[id].lazy; t[id].lazy=-1; } void push_up(int id) { t[id].val=t[ls].val+t[rs].val; } void build(int id,int l,int r) { if(l==r) { t[id].val=0; t[id].lazy=-1;//改成-1!切记! return; } int mid=(l+r)/2; build(ls,l,mid); build(rs,mid+1,r); push_up(id); } void insert(int id,int l,int r,int L,int R,int V) { if(r<L||l>R) return; if(r<=R && l>=L) { ans+=abs(V*(r-l+1)-t[id].val); t[id].val=V*(r-l+1); t[id].lazy=V; return; } int mid=(l+r)/2; push_down(id,l,mid,r); insert(ls,l,mid,L,R,V); insert(rs,mid+1,r,L,R,V); push_up(id); } void dfs1(int x,int pre) { in[x]=++num; fa[x]=pre; for (int i=0;i<lin[x].size();i++) { int nex=lin[x][i]; if (nex==pre) continue; dfs1(nex,x); } size[x]=num-in[x]+1;//必须+1,否则dfs2中判断叶子节点很麻烦。 } void dfs2(int x,int t) { in[x]=++num; top[x]=t; if (size[x]==1) return;//叶子节点直接返回,否则会死循环(不能用size[x]=0做!) int msize=0,heavy=0;//都要赋初始值! for (int i=0;i<lin[x].size();i++) { int nex=lin[x][i]; if (nex==fa[x]) continue; if (size[nex]>msize) { msize=size[nex]; heavy=nex; } } dfs2(heavy,t);//先走重儿子,其他随意 for (int i=0;i<lin[x].size();i++) { int nex=lin[x][i]; if (nex==fa[x] || nex==heavy) continue; dfs2(nex,nex); } } int main() { cin>>n; for (int i=1;i<n;i++) { int a; cin>>a;//编号都+1,防止爆线段树 lin[a+1].push_back(i+1); lin[i+1].push_back(a+1); } num=0; dfs1(1,0); num=0; dfs2(1,1); int q; cin>>q; char s[15]; while (q--) { int a; scanf("%s",s);//一定不要用cin!!!!T了半个小时... scanf("%d",&a); a++; if (s[0]=='i') { ans=0; while (a!=0) { insert(1,1,n,in[top[a]],in[a],1); a=fa[top[a]]; } printf("%d\n",ans); } if (s[0]=='u') { ans=0; insert(1,1,n,in[a],in[a]+size[a]-1,0); printf("%d\n",ans); } } }
相关文章推荐
- LVS集群的负载调度
- 使用反射调用匿名内部类时应该注意的一些地方
- C++函数指针
- 清除行列(程序员面试金典)
- ubutu下链接手机后 ,安装软件到手机 ----针对开发者
- 机器手臂(1):研究舵机固定支架
- orcal集群导入dmp文件
- ssh传输本地文件
- Autofac创建实例的方法总结
- 企业级工程输出log4j学习
- [ WARN ] Keyword 'Capture Page Screenshot' could not be runon failure: No browser isopen
- 1118有限自动机的构造与识别
- 进程与线程的一个简单解释(转)
- fread,read,fscanf,fput
- 微信开发笔记
- Mac下的常识操作
- Qt编程风格指南及命名约定
- js
- Linux下查看文件常用命令-cat,more,less,head,tail
- C语言学习总结(四) 剩余内容