【題解】
每個軟體只依賴另乙個軟體,且依賴關係不構成環,那麼很容易想到這是樹形結構。
我們用1表示以安裝,用0表示未安裝或已解除安裝;那麼安裝乙個軟體,就是把它到樹根的路徑上所有的點都改為1;解除安裝乙個軟體,就是把它的子樹全部改為0.
狀態改變的軟體包數就是操作前後整棵樹的點權和。
這樣我們直接樹鏈剖分即可。
1 #include2 #include3 #include4 #include5view code#define ll long long
6#define rg register
7#define n 100010
8#define ls (u<<1)
9#define rs (u<<1|1)
10#define mid ((a[u].l+a[u].r)>>1)
11#define len(x) (a[x].r-a[x].l+1)
12using
namespace
std;
13int
n,m,cnt,last,fa[n],hvy[n],top[n],dep[n],siz[n],dfn[n];
14 vectorson[n];
15struct
treea[n<<2
];18 inline int
read()
24void dfs1(int
x)30}31
void dfs2(int x,int
tp)37
void build(int u,int l,int
r)41 inline void pushdown(int
u)46
void update(int u,int l,int r,bool type)
52if
(a[u].mark) pushdown(u);
53if(l<=mid) update(ls,l,r,type);
54if(r>mid) update(rs,l,r,type);
55 a[u].sum=a[ls].sum+a[rs].sum;56}
57//
int query(int u,int l,int r)
64int
main()
71 dfs1(1); dfs2(1,1); build(1,1
,n);
72//
for(rg int i=1;i<=n;i++) printf("%d ",siz[i]); puts("siz");
73 m=read();
74while(m--)83}
84else update(1,dfn[x],dfn[x]+siz[x]-1,0
);85 printf("
%d\n
",abs(a[1].sum-last),a[1].sum); last=a[1
].sum;86}
87return0;
88 }
洛谷 pP2146 NOI2015 軟體包管理器
你決定設計你自己的軟體包管理器。不可避免地,你要解決軟體包之間的依賴問題。如果軟體包a依賴軟體包b,那麼安裝軟體包a以前,必須先安裝軟體包b。同時,如果想要解除安裝軟體包b,則必須解除安裝軟體包a。現在你已經獲得了所有的軟體包之間的依賴關係。而且,由於你之前的工作,除0號軟體包以外,在你的管理器當中...
洛谷 P2146 NOI2015 軟體包管理器
題解原發於我的blog 首先,很明顯這是一道樹鏈剖分的題。注意到乙個軟體只會以來乙個軟體,並且不會出現環,所以每次都可以連一條 x i 的邊。當安裝乙個軟體時,就把 1 x 的路徑上所有的點的轉態變為 1 但解除安裝乙個軟體時,就把 x 及它的所有的子樹變為 0 線段樹維護即可 推薦一道樹鏈剖分的好...
洛谷 P2146 NOI2015 軟體包管理器
如果乙個軟體被解除安裝,那答案就是它所有已安裝的子孫的個數 如果安裝,就是它到根的鏈上沒安裝的個數.注意修改lazy的時候 1 include2 include3 include4 include5 6using namespace std 78 int n,head 100001 rk 10000...