显然链剖 然而只询问到根的信息,不用管lca,要好些很多(虽然我没那么写)

对于安装 查询和维护到根路径

对于卸载 查询和维护子树信息

因为链剖本身是用dfs序建的线段树,所以使得查询和修改子树非常方便。

 #include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<algorithm> using namespace std; const int Maxn=;
int n;
struct Data{
int num[];
Data(int a=,int b=) {num[]=a,num[]=b;}
Data operator + (const Data&rhs) const {
return Data(num[]+rhs.num[],num[]+rhs.num[]);
}
}; struct SegmentTree{
Data da[Maxn*];
int tag[Maxn*];
int lft,rgt,w; void add_tag(int s,int l,int r,int w) {
if(w==-) return;
da[s].num[w]=r-l+;
da[s].num[w^]=;
tag[s]=w;
} void down(int s,int l,int r) {
if(tag[s]==- || l==r) return;
int mid=(l+r)>>;
add_tag(s<<,l,mid,tag[s]);
add_tag(s<<|,mid+,r,tag[s]);
tag[s]=-;
} void change(int s,int l,int r) {
if(lft<=l && r<=rgt) {
add_tag(s,l,r,w);
return;
}
down(s,l,r);
int mid=(l+r)>>;
if(lft<=mid) change(s<<,l,mid);
if(mid<rgt) change(s<<|,mid+,r);
da[s] = da[s<<] + da[s<<|];
}
Data query(int s,int l,int r) {
if(lft<=l&&r<=rgt) return da[s];
down(s,l,r);
int mid=(l+r)>>;
if(rgt<=mid) return query(s<<,l,mid);
if(mid<lft) return query(s<<|,mid+,r);
return query(s<<,l,mid) + query(s<<|,mid+,r);
}
void build(int s,int l,int r) {
if(l==r) {
da[s]=Data(,);
return;
}
int mid=(l+r)>>;
build(s<<,l,mid);
build(s<<|,mid+,r);
da[s]=da[s<<]+da[s<<|];
}
}seg; int sz[Maxn],fa[Maxn],son[Maxn],dep[Maxn]; struct Edge {
int to;
Edge*next;
Edge(int to=,Edge*next=):to(to),next(next) {}
}pool[Maxn*],*pis=pool,*fir[Maxn]; void AddEdge(int from,int to) {
*pis=Edge(to,fir[from]);fir[from]=pis++;
*pis=Edge(from,fir[to]);fir[to]=pis++;
} void dfs(int u) {
sz[u] = ;
son[u] = ;
for(Edge*p=fir[u];p;p=p->next) {
int v=p->to;
if(v==fa[u]) continue;
fa[v]=u;
dep[v]=dep[u]+;
dfs(v);
sz[u]+=sz[v];
if(sz[v]>sz[son[u]]) son[u]=v;
}
} int pos[Maxn],top[Maxn],tm,end[Maxn]; void build(int u,int pre) {
top[u] = pre;
pos[u] = ++tm;
if(son[u]) build(son[u],pre);
for(Edge*p=fir[u];p;p=p->next) {
int v=p->to;
if(v==fa[u] || v==son[u]) continue;
build(v,v);
}
end[u]=tm;
} Data query(int a,int b) {
int ta=top[a],tb=top[b];
Data ret;
for(;ta!=tb;a=fa[ta],ta=top[a]) {
if(dep[ta]<dep[tb]) swap(a,b) ,swap(ta,tb);
seg.lft=pos[ta],seg.rgt=pos[a];
ret=ret+seg.query(,,n);
}
if(dep[a]>dep[b]) swap(a,b);
seg.lft=pos[a],seg.rgt=pos[b];
Data tmp=seg.query(,,n);
return ret+tmp;
} void change(int a,int b,int c) {
int ta=top[a],tb=top[b];
Data ret;
for(;ta!=tb;a=fa[ta],ta=top[a]) {
if(dep[ta]<dep[tb]) swap(a,b) ,swap(ta,tb);
seg.lft=pos[ta],seg.rgt=pos[a];seg.w=c;
seg.change(,,n);
}
if(dep[a]>dep[b]) swap(a,b);
seg.lft=pos[a],seg.rgt=pos[b],seg.w=c;
return seg.change(,,n);
} void init() {
memset(seg.tag,-,sizeof seg.tag);
scanf("%d",&n);
for(int x,i=;i<n;i++) {
scanf("%d",&x);
AddEdge(i+,x+);
}
dfs();
build(,);
seg.build(,,n); // seg.lft=1,seg.rgt=n,seg.w=0;change(1,1,n);
} void work() {
int m,x;
char opt[];
for(scanf("%d",&m);m--;) {
scanf("%s%d",opt,&x);x++;
if(opt[]=='i') {
printf("%d\n",query(x,).num[]);
change(x,,);
}else {
seg.lft=pos[x],seg.rgt=end[x],seg.w=;
printf("%d\n",seg.query(,,n).num[]);
seg.change(,,n);
}
}
} int main() {
freopen("manager.in","r",stdin);
freopen("manager.out","w",stdout); init();
work(); return ;
}

NOI2015 软件包管理器 manager的更多相关文章

  1. 洛谷 P2146 [NOI2015]软件包管理器 树链剖分

    目录 题面 题目链接 题目描述 输入输出格式 输入格式: 输出格式: 输入输出样例 输入样例#1: 输出样例#1: 输入样例#2: 输出样例#2: 说明 说明 思路 AC代码 总结 题面 题目链接 P ...

  2. BZOJ 4196: [Noi2015]软件包管理器 [树链剖分 DFS序]

    4196: [Noi2015]软件包管理器 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 1352  Solved: 780[Submit][Stat ...

  3. [BZOJ4196][NOI2015]软件包管理器

    4196: [Noi2015]软件包管理器 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 1040  Solved: 603[Submit][Stat ...

  4. Bzoj 4196: [Noi2015]软件包管理器 树链剖分

    4196: [Noi2015]软件包管理器 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 721  Solved: 419[Submit][Statu ...

  5. [NOI2015]软件包管理器

    4621 [NOI2015]软件包管理器  题目等级 : 钻石 Diamond   题目描述 Description Linux用户和OSX用户一定对软件包管理器不会陌生.通过软件包管理器,你可以通过 ...

  6. BZOJ_4196_[Noi2015]软件包管理器_树链剖分

    BZOJ_4196_[Noi2015]软件包管理器_树链剖分 题意: Linux用户和OSX用户一定对软件包管理器不会陌生.通过软件包管理器,你可以通过一行命令安装某一个软件包,然后软件包管理器会帮助 ...

  7. bzoj 4196 [Noi2015]软件包管理器 (树链剖分+线段树)

    4196: [Noi2015]软件包管理器 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 2852  Solved: 1668[Submit][Sta ...

  8. 洛谷 P2146 [NOI2015]软件包管理器 解题报告

    P2146 [NOI2015]软件包管理器 题目描述 Linux用户和OSX用户一定对软件包管理器不会陌生.通过软件包管理器,你可以通过一行命令安装某一个软件包,然后软件包管理器会帮助你从软件源下载软 ...

  9. 【BZOJ4196】[Noi2015]软件包管理器 树链剖分

    [Noi2015]软件包管理器 树链剖分 Description Linux用户和OSX用户一定对软件包管理器不会陌生.通过软件包管理器,你可以通过一行命令安装某一个软件包,然后软件包管理器会帮助你从 ...

随机推荐

  1. 添加Appicon的方法

    1.将设计好的图片,拖拽到Groups&Files的Resources目录下: 2.修改Resources目录下的“工程名-info.plist”文件 3.修改该文件的Iconfile属性,填 ...

  2. 内容替换Filter

    有时候需要对网站进行控制,防止输出非法内容或者敏感信息.这时我们可以使用filter来进行内容替换,其工作原理为,在Servlet将内容输出到response时,response将内容缓存起来,在Fi ...

  3. POJ 2942.Knights of the Round Table (双连通)

    简要题解: 意在判断哪些点在一个图的  奇环的双连通分量内. tarjan求出所有的点双连通分量,再用二分图染色判断每个双连通分量是否形成了奇环,记录哪些点出现在内奇环内 输出没有在奇环内的点的数目 ...

  4. 24种设计模式--代理模式【Proxy Pattern】

    什么是代理模式呢?我很忙,忙的没空理你,那你要找我呢就先找我的代理人吧,那代理人总要知道被代理人能做哪些事情不能做哪些事情吧,那就是两个人具备同一个接口,代理人虽然不能干活,但是被代理的人能干活呀. ...

  5. JQUERY、AJAX双击DIV,直接修改DIV内的内容

    最近在做后台功能开发的时候,用到对排序字段的修改,感觉只为了修改一个排序值,而要重新进入编辑页比较麻烦,于是自己动手写…… 最近在做后台功能开发的时候,用到对排序字段的修改,感觉只为了修改一个排序值, ...

  6. underscorejs-partition学习

    2.25 partition 2.25.1 语法: _.partition(list, predicate, [context]) 2.25.2 说明: 拆分list为两个数组. 第一个数组的元素都满 ...

  7. [转] 翻译-高质量JavaScript代码书写基本要点 ---张鑫旭

    by zhangxinxu from http://www.zhangxinxu.com本文地址:http://www.zhangxinxu.com/wordpress/?p=1173 原文作者:St ...

  8. js登录页面的 回车事件

    js登录页面的 回车事件 js登录页面的 回车事件(2012-12-26 10:37:03)转载▼标签: jseventkey回车事件登录 分类: js.jquery  //回车事件 第一种docum ...

  9. 入门5:PHP 语法基础——流程控制

    一.if...else 语句 if( ) else{ } 如果 .... 就.... 否则.... if(判断){ 判断成立 则执行该表达式 }else{ 如果上方判断都不成立 则执行该表达式 } i ...

  10. C#【数据库】 Access类

    using System; using System.Data; using System.Data.OleDb; namespace AccessDb { /**//// <summary&g ...