您的位置:首页 > 其它

NOI2015 软件包管理器 树剖+线段树

2015-12-11 17:05 399 查看
题目背景是一个安装与卸载软件的系统,软件之间关系是一棵树,以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);
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: