1. 程式人生 > >BZOJ4196: [Noi2015]軟件包管理器(樹鏈剖分)

BZOJ4196: [Noi2015]軟件包管理器(樹鏈剖分)

linu scanf 空格 思路 通過 其中 如果 scrip read

Description

Linux用戶和OSX用戶一定對軟件包管理器不會陌生。通過軟件包管理器,你可以通過一行命令安裝某一個軟件包,然後軟件包管理器會幫助你從軟件源下載軟件包,同時自動解決所有的依賴(即下載安裝這個軟件包的安裝所依賴的其它軟件包),完成所有的配置。Debian/Ubuntu使用的apt-get,Fedora/CentOS使用的yum,以及OSX下可用的homebrew都是優秀的軟件包管理器。

你決定設計你自己的軟件包管理器。不可避免地,你要解決軟件包之間的依賴問題。如果軟件包A依賴軟件包B,那麽安裝軟件包A以前,必須先安裝軟件包B。同時,如果想要卸載軟件包B,則必須卸載軟件包A。現在你已經獲得了所有的軟件包之間的依賴關系。而且,由於你之前的工作,除0號軟件包以外,在你的管理器當中的軟件包都會依賴一個且僅一個軟件包,而0號軟件包不依賴任何一個軟件包。依賴關系不存在環(若有m(m≥2)個軟件包A1,A2,A3,…,Am,其中A1依賴A2,A2依賴A3,A3依賴A4,……,Am−1依賴Am,而Am依賴A1,則稱這m個軟件包的依賴關系構成環),當然也不會有一個軟件包依賴自己。 現在你要為你的軟件包管理器寫一個依賴解決程序。根據反饋,用戶希望在安裝和卸載某個軟件包時,快速地知道這個操作實際上會改變多少個軟件包的安裝狀態(即安裝操作會安裝多少個未安裝的軟件包,或卸載操作會卸載多少個已安裝的軟件包),你的任務就是實現這個部分。註意,安裝一個已安裝的軟件包,或卸載一個未安裝的軟件包,都不會改變任何軟件包的安裝狀態,即在此情況下,改變安裝狀態的軟件包數為0。

Input

輸入文件的第1行包含1個正整數n,表示軟件包的總數。軟件包從0開始編號。

隨後一行包含n−1個整數,相鄰整數之間用單個空格隔開,分別表示1,2,3,…,n−2,n−1號軟件包依賴的軟件包的編號。 接下來一行包含1個正整數q,表示詢問的總數。 之後q行,每行1個詢問。詢問分為兩種: installx:表示安裝軟件包x uninstallx:表示卸載軟件包x 你需要維護每個軟件包的安裝狀態,一開始所有的軟件包都處於未安裝狀態。對於每個操作,你需要輸出這步操作會改變多少個軟件包的安裝狀態,隨後應用這個操作(即改變你維護的安裝狀態)。

Output

輸出文件包括q行。

輸出文件的第i行輸出1個整數,為第i步操作中改變安裝狀態的軟件包數。

Sample Input

7
0 0 0 1 1 5
5
install 5
install 6
uninstall 1
install 4
uninstall 0

Sample Output

3
1
3
2
3

解題思路:

顯然這是一棵樹。

支持詢問到根節點有多少點被標記,清空子樹標記。

一顆線段樹,支持區間改為1/0。

維護樹鏈剖分序即可。

然而被卡常,開了O2才過,好蒟蒻啊QAQ

代碼:

  1 #pragma GCC optimize(2)
  2
#include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #define lll spc<<1 6 #define rrr spc<<1|1 7 inline int read() 8 { 9 int l=1; 10 int ret=0; 11 char ch=getchar(); 12 while(ch<0||ch>9) 13 { 14 if(ch==-) 15 l=-l; 16 ch=getchar(); 17 } 18 while(ch<=9&&ch>=0) 19 { 20 ret=ret*10+ch-0; 21 ch=getchar(); 22 } 23 return ret*l; 24 } 25 struct trnt{ 26 int val; 27 int len; 28 int lzt; 29 bool chg; 30 }tr[1000000]; 31 struct pnt{ 32 int hd; 33 int fa; 34 int dp; 35 int tp; 36 int ind; 37 int mxs; 38 int wgt; 39 }p[1000000]; 40 struct ent{ 41 int twd; 42 int lst; 43 }e[1000000]; 44 int cnt; 45 int n,m; 46 int dfn; 47 char cmd[100]; 48 void ade(int f,int t) 49 { 50 cnt++; 51 e[cnt].twd=t; 52 e[cnt].lst=p[f].hd; 53 p[f].hd=cnt; 54 } 55 void pushup(int spc) 56 { 57 tr[spc].val=tr[lll].val+tr[rrr].val; 58 tr[spc].len=tr[lll].len+tr[rrr].len; 59 return ; 60 } 61 void Add(int spc,int x) 62 { 63 tr[spc].val=tr[spc].len*x; 64 tr[spc].lzt=x; 65 tr[spc].chg=1; 66 return ; 67 } 68 void pushdown(int spc) 69 { 70 if(tr[spc].chg) 71 { 72 Add(lll,tr[spc].lzt); 73 Add(rrr,tr[spc].lzt); 74 tr[spc].chg=0; 75 } 76 return ; 77 } 78 void build(int l,int r,int spc) 79 { 80 if(l==r) 81 { 82 tr[spc].len=1; 83 return ; 84 } 85 int mid=(l+r)>>1; 86 build(l,mid,lll); 87 build(mid+1,r,rrr); 88 pushup(spc); 89 return ; 90 } 91 void update(int l,int r,int ll,int rr,int spc,int v) 92 { 93 if(l>rr||ll>r) 94 return ; 95 if(ll<=l&&r<=rr) 96 { 97 Add(spc,v); 98 return ; 99 } 100 pushdown(spc); 101 int mid=(l+r)>>1; 102 update(l,mid,ll,rr,lll,v); 103 update(mid+1,r,ll,rr,rrr,v); 104 pushup(spc); 105 return ; 106 } 107 int query(int l,int r,int ll,int rr,int spc) 108 { 109 if(ll>r||l>rr) 110 return 0; 111 if(ll<=l&&r<=rr) 112 return tr[spc].val; 113 pushdown(spc); 114 int mid=(l+r)>>1; 115 return query(l,mid,ll,rr,lll)+query(mid+1,r,ll,rr,rrr); 116 } 117 void Basic_dfs(int x,int f) 118 { 119 p[x].fa=f; 120 p[x].dp=p[f].dp+1; 121 p[x].wgt=1; 122 int maxs=-1; 123 for(int i=p[x].hd;i;i=e[i].lst) 124 { 125 int to=e[i].twd; 126 if(to==f) 127 continue; 128 Basic_dfs(to,x); 129 p[x].wgt+=p[to].wgt; 130 if(maxs<p[to].wgt) 131 { 132 maxs=p[to].wgt; 133 p[x].mxs=to; 134 } 135 } 136 return ; 137 } 138 void Build_dfs(int x,int top) 139 { 140 if(!x) 141 return ; 142 p[x].ind=++dfn; 143 p[x].tp=top; 144 Build_dfs(p[x].mxs,top); 145 for(int i=p[x].hd;i;i=e[i].lst) 146 { 147 int to=e[i].twd; 148 if(p[to].ind) 149 continue; 150 Build_dfs(to,to); 151 } 152 } 153 int Install(int x) 154 { 155 int ans=0; 156 while(p[x].tp!=1) 157 { 158 ans+=p[x].dp-p[p[x].tp].dp-query(1,dfn,p[p[x].tp].ind,p[x].ind,1)+1; 159 update(1,dfn,p[p[x].tp].ind,p[x].ind,1,1); 160 x=p[p[x].tp].fa; 161 } 162 ans+=p[x].dp-query(1,dfn,p[1].ind,p[x].ind,1); 163 update(1,dfn,p[1].ind,p[x].ind,1,1); 164 return ans; 165 } 166 int Uninstall(int x) 167 { 168 int ans=query(1,dfn,p[x].ind,p[x].ind+p[x].wgt-1,1); 169 update(1,dfn,p[x].ind,p[x].ind+p[x].wgt-1,1,0); 170 return ans; 171 } 172 int main() 173 { 174 n=read(); 175 for(int i=2;i<=n;i++) 176 { 177 int x=read(); 178 x++; 179 ade(x,i); 180 ade(i,x); 181 } 182 dfn=0; 183 Basic_dfs(1,1); 184 Build_dfs(1,1); 185 build(1,dfn,1); 186 m=read(); 187 while(m--) 188 { 189 scanf("%s",cmd+1); 190 int x=read(); 191 x++; 192 if(cmd[1]==i) 193 printf("%d\n",Install(x)); 194 else 195 printf("%d\n",Uninstall(x)); 196 } 197 return 0; 198 }

BZOJ4196: [Noi2015]軟件包管理器(樹鏈剖分)