NC50486. 软件包管理器
描述
输入描述
输入文件的第1行包含1个正整数n,表示软件包的总数。软件包从0开始编号。
随后一行包含n−1个整数,相邻整数之间用单个空格隔开,分别表示号软件包依赖的软件包的编号。
接下来一行包含一个正整数q,表示询问的总数。
之后q行,每行一个询问。询问分为两种:
install x:表示安装软件包x
uninstall x:表示卸载软件包x
你需要维护每个软件包的安装状态,一开始所有的软件包都处于未安装状态。对于每个操作,你需要输出这步操作会改变多少个软件包的安装状态,随后应用这个操作(即改变你维护的安装状态)。
输出描述
输出文件包括q行。输出文件的第i行输出一个整数,为第i步操作中改变安装状态的软件包数。
示例1
输入:
7 0 0 0 1 1 5 5 install 5 install 6 uninstall 1 install 4 uninstall 0
输出:
3 1 3 2 3
说明:
一开始所有的软件包都处于未安装状态。Java 解法, 执行用时: 1838ms, 内存消耗: 48136K, 提交时间: 2021-09-20 16:13:49
import java.io.PrintWriter; import java.util.Arrays; import java.util.Scanner; public class Main { public static void main(String args[]){ new Main().solve(); } Scanner in; PrintWriter out; public void solve(){ in = new Scanner(System.in); out = new PrintWriter(System.out); go(); } long s[]; long mx[]; long f[]; void build(int id,int left,int right){ if(left==right){ s[id] = f[left]; mx[id] = -1; return; } int mid = (left+right)/2; build(id*2,left,mid); build(id*2+1,mid+1,right); s[id] = s[id*2] + s[id*2+1]; } long qry(int id,int left,int right,int l,int r){ if(left>=l&&right<=r){ return s[id]; }else if(left>r||right<l){ return 0; } int mid = (left+right)/2; if(mx[id]!=-1){ mx[id*2] = mx[id]; mx[id*2+1] = mx[id]; s[id*2] = mx[id]*(mid-left+1); s[id*2+1] = mx[id]*(right-(mid+1)+1); mx[id] = -1; } long v1 = qry(id*2,left,mid,l,r); long v2 = qry(id*2+1,mid+1,right,l,r); s[id] = s[id*2] + s[id*2+1]; return v1+v2; } // void update(int id,int left,int right,int l,long val){ // if(left>l||right<l){ // return; // }else if(left==right){ // s[id] += val; // return; // } // int mid = (left+right)/2; // if(mx[id]!=0){ // mx[id*2] += mx[id]; // mx[id*2+1] += mx[id]; // // s[id*2] += mx[id]*(mid-left+1); // s[id*2+1] += mx[id]*(right-(mid+1)+1); // // // mx[id] = 0; // } // // update(id*2,left,mid,l,val); // update(id*2+1,mid+1,right,l,val); // s[id] = s[id*2] + s[id*2+1]; // // } void update(int id,int left,int right,int l,int r,long val){ if(left>r||right<l){ return; }else if(left>=l&&right<=r){ mx[id] = val; s[id] = (right-left+1)*val; return; } int mid = (left+right)/2; if(mx[id]!=-1){ mx[id*2] = mx[id]; mx[id*2+1] = mx[id]; s[id*2] = mx[id]*(mid-left+1); s[id*2+1] = mx[id]*(right-(mid+1)+1); mx[id] = -1; } update(id*2,left,mid,l,r,val); update(id*2+1,mid+1,right,l,r,val); s[id] = s[id*2] + s[id*2+1]; } int h[],ne[],to[],wt[]; int ct = 0; void add(int u,int v){ to[ct] = v; ne[ct] = h[u]; h[u] = ct++; } int n; void go(){ n = in.nextInt(); h = new int[n]; Arrays.fill(h,-1); ne = new int[2*(n-1)]; to = new int[2*(n-1)]; wt = new int[n]; fa = new int[n]; dep = new int[n]; top = new int[n]; son = new int[n]; sz = new int[n]; Arrays.fill(sz,1); dfn = new int[n]; pt = new int[n]; gpt = new int[n]; stk = new int[n]; // for(int i= 0;i<n;++i){ // wt[i] = in.nextInt(); // } for(int i=1;i<=n-1;++i){ // int u = in.nextInt()-1; int u = i; int v = in.nextInt(); add(u,v); add(v,u); } int q = in.nextInt(); // dfs1(0); // dfs2(0); treeLink(0); f = new long[n]; // for(int i=0;i<n;++i){ // f[i] = wt[pt[i]]; // } s = new long[n*4]; mx = new long[n*4]; build(1,0,n-1); for(int i=0;i<q;++i){ String c = in.next(); if("install".equals(c)){ int uu = in.nextInt(); int u = uu; long r = 0; int tot = dep[u]+1; while(top[u]!=0){ long p = qry(1,0,n-1,dfn[top[u]],dfn[u]); r+= p; u = fa[top[u]]; } long p = qry(1,0,n-1,dfn[0],dfn[u]); r += p; out.println(tot-r); u = uu; while(top[u]!=0){ update(1,0,n-1,dfn[top[u]],dfn[u],1); u = fa[top[u]]; } update(1,0,n-1,dfn[0],dfn[u],1); }else{ int u = in.nextInt(); //int tot = sz[u]; long r = qry(1,0,n-1,dfn[u], dfn[u]+sz[u]-1); out.println(r); update(1,0,n-1,dfn[u], dfn[u]+sz[u]-1, 0); } } out.close(); } int fa[],dep[],top[],son[],sz[],dfn[],pt[],gpt[],stk[]; void dfs1(int rt){ sz[rt] = 1; for(int i=h[rt];i!=-1;i=ne[i]){ int v = to[i]; if(v==fa[rt]) continue; fa[v] = rt; dep[v] = dep[rt] + 1; dfs1(v); sz[rt] += sz[v]; if(son[rt]==0||sz[son[rt]]<sz[v]){ son[rt] = v; } } } int id = 0; void dfs2(int rt){ dfn[rt] = id; pt[id++] = rt; if(son[rt]!=0){ top[son[rt]] = top[rt]; dfs2(son[rt]); } for(int i=h[rt];i!=-1;i=ne[i]){ int v = to[i]; if(v==fa[rt]||v==son[rt]) continue; top[v] = v; dfs2(v); } } public void treeLink(int ort){ int p = 0; stk[p++] = ort; int clock = 0; int rt = -1; while(p>0) { rt = stk[--p]; gpt[clock++] = rt; for (int i = h[rt]; i != -1; i = ne[i]) { int v = to[i]; if (fa[rt] == v) continue; fa[v] = rt; dep[v] = dep[rt] + 1; stk[p++] = v; } } for(int i=n-1;i>0;--i){ int cur = gpt[i]; int fat = fa[cur]; sz[fat] += sz[cur]; if (son[fat]== 0 || sz[cur] > sz[son[fat]]) { son[fat] = cur; } } for (int i = 1; i < n; i++) top[gpt[i]] = gpt[i] == son[fa[gpt[i]]] ? top[fa[gpt[i]]] : gpt[i]; p = 0; stk[p++] = ort; while(p>0) { rt = stk[--p]; dfn[rt] = id; pt[id++] = rt; for (int i = h[rt]; i != -1; i = ne[i]) { int v = to[i]; if (fa[rt] == v || v == son[rt]) continue; stk[p++] = v; } if(son[rt]!=0) { stk[p++] = son[rt]; } } } }
C++14(g++5.4) 解法, 执行用时: 667ms, 内存消耗: 12012K, 提交时间: 2020-01-28 17:38:19
#include<bits/stdc++.h> using namespace std; const int MAXN = 1e5+1; int N; vector<int> G[MAXN]; int fa[MAXN]; int siz[MAXN]; int dep[MAXN]; int top[MAXN]; int son[MAXN]; int dfn[MAXN]; int dfe[MAXN]; int rnk[MAXN]; int clk; void dfs1(int s, int f) { // cout << s << " " << f << endl; if (f!=-1) dep[s] = dep[f]+1; siz[s] = 1; fa[s] = f; for (auto t: G[s]) if (t != f) { dfs1(t, s); siz[s] += siz[t]; if (son[s] == -1 || siz[son[s]] < siz[t]) son[s] = t; } } void dfs2(int s, int f, int tp) { top[s] = tp; dfn[s] = ++clk; rnk[clk] = s; if (son[s] != -1) dfs2(son[s], s, tp); for (auto t:G[s]) if (t != f && t != son[s]) dfs2(t, s, t); dfe[s] = clk; } int sum[MAXN*4]; bool is_delay[MAXN*4]; int delay[MAXN*4]; void change(int o, int l, int r, int L, int R, int v); void push_down(int o, int l, int m, int r) { if (!is_delay[o]) return; is_delay[o] = false; change(o*2, l, m, l, m, delay[o]); change(o*2+1, m+1, r, m+1,r, delay[o]); } void change(int o, int l, int r, int L, int R, int v) { if (R < l || r < L) return; if (L <= l && r <= R) { sum[o] = v * (r - l + 1); is_delay[o] = true; delay[o] = v; return; } int m = (l+r)/2; push_down(o, l, m, r); change(o*2, l, m, L, R, v); change(o*2+1, m+1, r, L, R, v); sum[o] = sum[o*2] + sum[o*2+1]; } int query(int o, int l, int r, int L, int R) { if (R < l || r < L) return 0; if (L <= l && r <= R) return sum[o]; int m = (l+r)/2; push_down(o, l, m, r); return query(o*2, l, m, L, R) + query(o*2+1, m+1, r, L, R); } int main() { cin >> N; for (int i = 1; i < N; i++) { int u; cin >> u; G[u].push_back(i); } memset(son, -1, sizeof(son)); dfs1(0, -1); dfs2(0, -1, 0); // cout << "init done: " << clk << endl; int M; cin >> M; while (M--) { string op; int x; cin >> op >> x; if (op == "install") { int pre = query(1, 1, clk, 1, clk); while (x != -1) { change(1, 1, clk, dfn[top[x]], dfn[x], 1); x = fa[top[x]]; } int pos = query(1, 1, clk, 1, clk); cout << pos - pre << endl; } else { int pre = query(1, 1, clk, 1, clk); change(1, 1, clk, dfn[x], dfe[x], 0); int pos = query(1, 1, clk, 1, clk); cout << pre - pos << endl; } } }
C++11(clang++ 3.9) 解法, 执行用时: 354ms, 内存消耗: 11244K, 提交时间: 2020-05-30 22:09:04
#include<bits/stdc++.h> using namespace std; const int NN=100004; int tim,dep[NN],dfn[NN],tp[NN],fa[NN],sz[NN],h[NN],s[NN<<2],tg[NN<<2]; vector<int> g[NN]; void dfs1(int x) { dep[x]=dep[fa[x]]+1; sz[x]=1; for(int i=0,y;i<g[x].size();i++) { fa[y=g[x][i]]=x; dfs1(y); sz[x]+=sz[y]; h[x]=sz[y]>sz[h[x]]?y:h[x]; } } void dfs2(int x) { dfn[x]=++tim; if(h[x]) { tp[h[x]]=tp[x]; dfs2(h[x]); } for(int i=0;i<g[x].size();i++) if(g[x][i]!=h[x]) { tp[g[x][i]]=g[x][i]; dfs2(g[x][i]); } } void segtree(int x,int l,int r,int L,int R,int v) { if(L<=l&&r<=R) { s[x]=v?r-l+1:0; tg[x]=v; return; } int mid=l+r>>1; if(~tg[x]) { tg[x<<1]=tg[x<<1|1]=tg[x]; s[x<<1]=tg[x]?mid-l+1:0; s[x<<1|1]=tg[x]?r-mid:0; tg[x]=-1; } if(L<=mid) segtree(x<<1,l,mid,L,R,v); if(R>mid) segtree(x<<1|1,mid+1,r,L,R,v); s[x]=s[x<<1]+s[x<<1|1]; } int main() { ios::sync_with_stdio(false),cin.tie(0); int n; cin>>n; for(int i=2;i<=n;i++) { int u; cin>>u; u++; g[u].push_back(i); } tp[1]=1; dfs1(1); dfs2(1); memset(tg,-1,sizeof(tg)); int t; cin>>t; while(t--) { char opt[15]; int x,st; cin>>opt>>x; x++; st=s[1]; if(opt[0]=='i') for(;x;x=fa[tp[x]]) segtree(1,1,n,dfn[tp[x]],dfn[x],1); else segtree(1,1,n,dfn[x],dfn[x]+sz[x]-1,0); cout<<abs(st-s[1])<<endl; } return 0; }