码迷,mamicode.com
首页 > 其他好文 > 详细

NOI2015 软件包管理器 manager

时间:2015-07-18 09:29:17      阅读:105      评论:0      收藏:0      [点我收藏+]

标签:

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

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

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

因为链剖本身是用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 }

 

NOI2015 软件包管理器 manager

标签:

原文地址:http://www.cnblogs.com/showson/p/4656203.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!