洛谷 2146 NOI2015 軟體包管理器

2022-09-06 17:21:10 字數 1663 閱讀 5901

【題解】

每個軟體只依賴另乙個軟體,且依賴關係不構成環,那麼很容易想到這是樹形結構。

我們用1表示以安裝,用0表示未安裝或已解除安裝;那麼安裝乙個軟體,就是把它到樹根的路徑上所有的點都改為1;解除安裝乙個軟體,就是把它的子樹全部改為0.

狀態改變的軟體包數就是操作前後整棵樹的點權和。

這樣我們直接樹鏈剖分即可。

1 #include2 #include3 #include4 #include5

#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 }

view code

洛谷 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...