NOI2015 软件包管理器 manager

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

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

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

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

  1 #include<iostream>
  2 #include<cstring>
  3 #include<cstdlib>
  4 #include<cstdio>
  5 #include<algorithm>
  6
  7 using namespace std;
  8
  9 const int Maxn=100010;
 10 int n;
 11 struct Data{
 12     int num[2];
 13     Data(int a=0,int b=0) {num[0]=a,num[1]=b;}
 14     Data operator + (const Data&rhs) const {
 15         return Data(num[0]+rhs.num[0],num[1]+rhs.num[1]);
 16     }
 17 };
 18
 19 struct  SegmentTree{
 20     Data da[Maxn*4];
 21     int tag[Maxn*4];
 22     int lft,rgt,w;
 23
 24     void add_tag(int s,int l,int r,int w) {
 25         if(w==-1) return;
 26         da[s].num[w]=r-l+1;
 27         da[s].num[w^1]=0;
 28         tag[s]=w;
 29     }
 30
 31     void down(int s,int l,int r) {
 32         if(tag[s]==-1 || l==r) return;
 33         int mid=(l+r)>>1;
 34         add_tag(s<<1,l,mid,tag[s]);
 35         add_tag(s<<1|1,mid+1,r,tag[s]);
 36         tag[s]=-1;
 37     }
 38
 39     void change(int s,int l,int r) {
 40         down(s,l,r);
 41         if(lft<=l && r<=rgt) {
 42             add_tag(s,l,r,w);
 43             return;
 44         }
 45         int mid=(l+r)>>1;
 46         if(lft<=mid) change(s<<1,l,mid);
 47         if(mid<rgt) change(s<<1|1,mid+1,r);
 48         da[s] = da[s<<1] + da[s<<1|1];
 49     }
 50     Data query(int s,int l,int r) {
 51         down(s,l,r);
 52         if(lft<=l&&r<=rgt) return da[s];
 53         int mid=(l+r)>>1;
 54         if(rgt<=mid) return query(s<<1,l,mid);
 55         if(mid<lft) return query(s<<1|1,mid+1,r);
 56         return query(s<<1,l,mid) + query(s<<1|1,mid+1,r);
 57     }
 58     void build(int s,int l,int r) {
 59         if(l==r) {
 60             da[s]=Data(1,0);
 61             return;
 62         }
 63         int mid=(l+r)>>1;
 64         build(s<<1,l,mid);
 65         build(s<<1|1,mid+1,r);
 66         da[s]=da[s<<1]+da[s<<1|1];
 67     }
 68 }seg;
 69
 70 int sz[Maxn],fa[Maxn],son[Maxn],dep[Maxn];
 71
 72 struct Edge {
 73     int to;
 74     Edge*next;
 75     Edge(int to=0,Edge*next=0):to(to),next(next) {}
 76 }pool[Maxn*2],*pis=pool,*fir[Maxn];
 77
 78 void AddEdge(int from,int to) {
 79     *pis=Edge(to,fir[from]);fir[from]=pis++;
 80     *pis=Edge(from,fir[to]);fir[to]=pis++;
 81 }
 82
 83 void dfs(int u) {
 84     sz[u] = 1;
 85     son[u] = 0;
 86     for(Edge*p=fir[u];p;p=p->next) {
 87         int v=p->to;
 88         if(v==fa[u]) continue;
 89         fa[v]=u;
 90         dep[v]=dep[u]+1;
 91         dfs(v);
 92         sz[u]+=sz[v];
 93         if(sz[v]>sz[son[u]]) son[u]=v;
 94     }
 95 }
 96
 97 int pos[Maxn],top[Maxn],tm,end[Maxn];
 98
 99 void build(int u,int pre) {
100     top[u] = pre;
101     pos[u] = ++tm;
102     if(son[u]) build(son[u],pre);
103     for(Edge*p=fir[u];p;p=p->next) {
104         int v=p->to;
105         if(v==fa[u] || v==son[u]) continue;
106         build(v,v);
107     }
108     end[u]=tm;
109 }
110
111 Data query(int a,int b) {
112     int ta=top[a],tb=top[b];
113     Data ret;
114     for(;ta!=tb;a=fa[ta],ta=top[a]) {
115         if(dep[ta]<dep[tb]) swap(a,b) ,swap(ta,tb);
116         seg.lft=pos[ta],seg.rgt=pos[a];
117         ret=ret+seg.query(1,1,n);
118     }
119     if(dep[a]>dep[b]) swap(a,b);
120     seg.lft=pos[a],seg.rgt=pos[b];
121     Data tmp=seg.query(1,1,n);
122     return ret+tmp;
123 }
124
125 void change(int a,int b,int c) {
126     int ta=top[a],tb=top[b];
127     Data ret;
128     for(;ta!=tb;a=fa[ta],ta=top[a]) {
129         if(dep[ta]<dep[tb]) swap(a,b) ,swap(ta,tb);
130         seg.lft=pos[ta],seg.rgt=pos[a];seg.w=c;
131         seg.change(1,1,n);
132     }
133     if(dep[a]>dep[b]) swap(a,b);
134     seg.lft=pos[a],seg.rgt=pos[b],seg.w=c;
135     return seg.change(1,1,n);
136 }
137
138 void init() {
139     memset(seg.tag,-1,sizeof seg.tag);
140     scanf("%d",&n);
141     for(int x,i=1;i<n;i++) {
142         scanf("%d",&x);
143         AddEdge(i+1,x+1);
144     }
145     dfs(1);
146     build(1,1);
147     seg.build(1,1,n);
148
149 //    seg.lft=1,seg.rgt=n,seg.w=0;change(1,1,n);
150 }
151
152 void work() {
153     int m,x;
154     char opt[100];
155     for(scanf("%d",&m);m--;) {
156         scanf("%s%d",opt,&x);x++;
157         if(opt[0]==‘i‘) {
158             printf("%d\n",query(x,1).num[0]);
159             change(x,1,1);
160         }else {
161             seg.lft=pos[x],seg.rgt=end[x],seg.w=0;
162             printf("%d\n",seg.query(1,1,n).num[1]);
163             seg.change(1,1,n);
164         }
165     }
166 }
167
168 int main() {
169     freopen("manager.in","r",stdin);
170     freopen("manager.out","w",stdout);
171
172     init();
173     work();
174
175     return 0;
176 }
时间: 2024-10-25 10:20:22

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

BZOJ 4196: [Noi2015]软件包管理器

二次联通门 : BZOJ 4196: [Noi2015]软件包管理器 /* BZOJ 4196: [Noi2015]软件包管理器 树链剖分 树链剖分 , 用线段树维护链上的和与子树的和 对于1操作, 每次预先查询待修改点x点的深度 后查询1到x这条链上有多少已安装的, 然后上面的值减下面的值 对于2操作,每次查询以x为根的子树的大小 修改整颗子树即可.. 说白了其实就是板子题 */ #include <cstdio> #define Max 500090 inline int min (int

【BZOJ 4196】[Noi2015]软件包管理器

[Noi2015]软件包管理器 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 331  Solved: 199[Submit][Status][Discuss] Description Linux用户和OSX用户一定对软件包管理器不会陌生.通过软件包管理器,你可以通过一行命令安装某一个软件包,然后软件包管理器会帮助你从软件源下载软件包,同时自动解决所有的依赖(即下载安装这个软件包的安装所依赖的其它软件包),完成所有的配置.Debian/Ubunt

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

4196: [Noi2015]软件包管理器 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 721  Solved: 419[Submit][Status][Discuss] Description Linux用户和OSX用户一定对软件包管理器不会陌生.通过软件包管理器,你可以通过一行命令安装某一个软件包,然后软件包管理器会帮助你从软件源下载软件包,同时自动解决所有的依赖(即下载安装这个软件包的安装所依赖的其它软件包),完成所有的配置.Debian

NOI2015软件包管理器

P2106 - [NOI2015]软件包管理器 Description 你决定设计你自己的软件包管理器.不可避免的,你要解决软件包之间的依赖关系.如果A依赖B,那么安装A之前需安装B,卸载B之前须卸载A.0号软件包不依赖任何软件包.依赖关系不存在环(包括自环). 你的任务是,求出每次安装.删除操作会改变多少个包的状态. 安装一个已安装的软件包,或者卸载一个未安装的软件包,都不会改变任何软件包的安装状态,即在此情况下,改变安装状态的软件包数为0 每次操作不仅需要计算安装软件包数,还作为操作影响后来

洛谷 P2146 [NOI2015]软件包管理器 (树链剖分模板题)

题目描述 Linux用户和OSX用户一定对软件包管理器不会陌生.通过软件包管理器,你可以通过一行命令安装某一个软件包,然后软件包管理器会帮助你从软件源下载软件包,同时自动解决所有的依赖(即下载安装这个软件包的安装所依赖的其它软件包),完成所有的配置.Debian/Ubuntu使用的apt-get,Fedora/CentOS使用的yum,以及OSX下可用的homebrew都是优秀的软件包管理器. 你决定设计你自己的软件包管理器.不可避免地,你要解决软件包之间的依赖问题.如果软件包A依赖软件包B,那

[Noi2015]软件包管理器

题目描述 Linux用户和OSX用户一定对软件包管理器不会陌生.通过软件包管理器,你可以通过一行命令安装某一个软件包,然后软件包管理器会帮助你从软件源下载软件包,同时自动解决所有的依赖(即下载安装这个软件包的安装所依赖的其它软件包),完成所有的配置.Debian/Ubuntu使用的apt-get,Fedora/CentOS使用的yum,以及OSX下可用的homebrew都是优秀的软件包管理器. 你决定设计你自己的软件包管理器.不可避免地,你要解决软件包之间的依赖问题.如果软件包A依赖软件包B,那

BZOJ4196 [NOI2015] 软件包管理器

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=4196,http://uoj.ac/problem/128 Description Linux用户和OSX用户一定对软件包管理器不会陌生.通过软件包管理器,你可以通过一行命令安装某一个软件包,然后软件包管理器会帮助你从软件源下载软件包,同时自动解决所有的依赖(即下载安装这个软件包的安装所依赖的其它软件包),完成所有的配置.Debian/Ubuntu使用的apt-get,Fedora/Cen

4196: [Noi2015]软件包管理器

Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 412  Solved: 251[Submit][Status][Discuss] Description Linux用户和OSX用户一定对软件包管理器不会陌生.通过软件包管理器,你可以通过一行命令安装某一个软件包,然后软件包管理器会帮助你从软件源下载软件包,同时自动解决所有的依赖(即下载安装这个软件包的安装所依赖的其它软件包),完成所有的配置.Debian/Ubuntu使用的apt-get,Fedo

[UOJ#128][BZOJ4196][Noi2015]软件包管理器

试题描述 Linux用户和OSX用户一定对软件包管理器不会陌生.通过软件包管理器,你可以通过一行命令安装某一个软件包,然后软件包管理器会帮助你从软件源下载软件包,同时自动解决所有的依赖(即下载安装这个软件包的安装所依赖的其它软件包),完成所有的配置.Debian/Ubuntu使用的apt-get,Fedora/CentOS使用的yum,以及OSX下可用的homebrew都是优秀的软件包管理器. 你决定设计你自己的软件包管理器.不可避免地,你要解决软件包之间的依赖问题.如果软件包A依赖软件包B,那