NOI2015 软件包管理器 树剖+线段树
来源:互联网 发布:mysql自定义排序规则 编辑:程序博客网 时间:2024/06/07 15:38
题目背景是一个安装与卸载软件的系统,软件之间关系是一棵树,以0为根节点。当你安装一个软件时需要先安装它的所有祖先,卸载时则要先卸载整个子树。对每一次操作询问改变状态的软件数目。
思路: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); } }}
1 0
- NOI2015 软件包管理器 树剖+线段树
- 【树链剖分+线段树】[noi2015]软件包管理器
- 【BZOJ4196】[Noi2015]软件包管理器【树链剖分】【线段树】
- noi2015 软件包管理器 树链剖分 + 线段树维护
- |BZOJ 4196|树链剖分|线段树|[Noi2015]软件包管理器
- 【BZOJ4196】【NOI2015】软件包管理器(树链剖分,线段树)
- bzoj4196: [Noi2015]软件包管理器
- 【NOI2015】【BZOJ4196】软件包管理器
- 【NOI2015】【软件包管理器】【树链剖分】
- [BZOJ4196][Noi2015]软件包管理器
- bzoj4196[Noi2015]软件包管理器
- bzoj4196【NOI2015】软件包管理器
- bzoj4196软件包管理器 noi2015
- [BZOJ4196] [Noi2015]软件包管理器
- [题解][NOI2015]软件包管理器
- #128. 【NOI2015】软件包管理器
- 【NOI2015】BZOJ4196软件包管理器
- noi2015 d1t2 软件包管理器
- UICollectionView的用法小结
- HDU1251 统计难题 字典树裸题
- QT 实现QLabel上的超链接
- linux命令-tar
- 今天的问题
- NOI2015 软件包管理器 树剖+线段树
- log4j
- 查看页面,强制以高级浏览器打开
- 【Android】开源 闲暇(Leisure) 阅读类应用的开发
- poj 2818 Making Change 枚举
- 第二讲:HTML5&Cordova(学习笔记)
- $.grep()函数——javascript中类似Lambda表达式的实现形式
- too many open files
- 使用HTML5来实现本地文件读取和写入