1. 程式人生 > >[NOI2015]軟件包管理器(樹鏈刨分)

[NOI2015]軟件包管理器(樹鏈刨分)

struct bits const target uil turn install query cin

其實也算是個板子吧,思想還是很好的

一開始真的沒什麽思路,然後想了想要是這個軟件已經裝上了就設成1,不然設成0,

查詢的話直接做點到根節點的權值和就好了,要是卸載了,就查詢這個點為為根節點的權值和,然後用子樹大小減去上面的權值和就好了

區間覆蓋的話將lazytag改動一下就好了

題面

放上醜醜的代碼

#include<bits/stdc++.h>
#define ls(x) x<<1
#define rs(x) x<<1|1
using namespace std;
const int N=4e5+6;
int m,n,k,p,l,cnt,tot,res,root;
int lg[N],sum[N],son[N],fa[N],dep[N],top[N],head[N],size[N],id[N]; struct edge { int nx,to; } e[N]; void add_edge(int a,int b) { cnt++;e[cnt].to=b;e[cnt].nx=head[a];head[a]=cnt; cnt++;e[cnt].to=a;e[cnt].nx=head[b];head[b]=cnt; } void push_up(int p) { sum[p]=sum[ls(p)]+sum[rs(p)]; }
void build(int p,int l,int r) { lg[p]=-1; if (l==r) { sum[p]=1; return; } int mid=(l+r)>>1; build(ls(p),l,mid); build(rs(p),mid+1,r); push_up(p); } void push_down(int p,int lenn) { if (lg[p]==-1) return; lg[ls(p)]=lg[p]; lg[rs(p)]
=lg[p]; sum[ls(p)]=lg[p]*(lenn-(lenn>>1)); sum[rs(p)]=lg[p]*(lenn>>1); lg[p]=-1; } void update(int p,int l,int r,int nl,int nr,int k) { if (nl<=l&&r<=nr) { sum[p]=(r-l+1)*k; lg[p]=k; return; } push_down(p,(r-l+1)); int mid=(l+r)>>1; if (nl<=mid) update(ls(p),l,mid,nl,nr,k); if (nr>mid) update(rs(p),mid+1,r,nl,nr,k); push_up(p); } void query(int p,int l,int r,int xl,int xr) { if (xl<=l&&r<=xr) { res+=sum[p]; return; } push_down(p,(r-l+1)); int mid=(l+r)>>1; if (xl<=mid) query(ls(p),l,mid,xl,xr); if (xr>mid) query(rs(p),mid+1,r,xl,xr); } void dfs1(int x,int f,int deep) { dep[x]=deep; fa[x]=f; size[x]=1; int maxson=-1; for (int i=head[x];i;i=e[i].nx) { int y=e[i].to; if (y==fa[x]) continue; dfs1(y,x,deep+1); size[x]+=size[y]; if (size[y]>maxson) {son[x]=y;maxson=size[y];} } } void dfs2(int x,int topf) { id[x]=++tot; top[x]=topf; if (!son[x]) return; dfs2(son[x],topf); for (int i=head[x];i;i=e[i].nx) { int y=e[i].to; if (y==fa[x]||y==son[x]) continue; dfs2(y,y); } } int queson(int x) { int ans=0; res=0; query(1,1,n,id[x],id[x]+size[x]-1); ans=res; return ans; } int querange(int x,int y) { int ans=0; while (top[x]!=top[y]) { if(dep[top[x]]<dep[top[y]]) swap(x,y); res=0; query(1,1,n,id[top[x]],id[x]); ans+=res; x=fa[top[x]]; } if (dep[x]>dep[y]) swap(x,y); res=0; query(1,1,n,id[x],id[y]); ans+=res; return ans; } void uprange(int x,int y,int k) { while (top[x]!=top[y]) { if (dep[top[x]]<dep[top[y]]) swap(x,y); update(1,1,n,id[top[x]],id[x],k); x=fa[top[x]]; } if (dep[x]>dep[y]) swap(x,y); update(1,1,n,id[x],id[y],k); } int main() { scanf("%d",&n); root=1; for (int i=1;i<=n-1;i++) { int x; scanf("%d",&x); x++; add_edge(x,i+1); } dfs1(root,0,1); dfs2(root,root); build(1,1,n); scanf("%d",&m); string s;int x; for (int i=1;i<=m;i++) { cin>>s; scanf("%d",&x); x++; if (s=="install") {printf("%d\n",querange(x,root));uprange(x,root,0);} if (s=="uninstall") {printf("%d\n",size[x]-queson(x));update(1,1,n,id[x],id[x]+size[x]-1,1);} } return 0; }

[NOI2015]軟件包管理器(樹鏈刨分)