~~~題面~~~
題解:首先我們觀察到0號不會依賴別人,而其他的軟體都會依賴且僅會依賴乙個軟體。因此這是一棵樹。
於是我們在看看要支援一些什麼操作。
1,安裝乙個軟體要改變多少軟體的狀態。
如果將乙個軟體與所依賴的軟體相連,那麼可能要改變的狀態就是它自己和往上走直到根的那條鏈上的點。
2,解除安裝乙個軟體要改變多少軟體的狀態
顯然是自己+子樹。
那麼我們可以想到什麼呢?
樹鏈剖分!
安裝就查詢從自己往上走的點中有多少已經被安裝。
deep[x](deep[0] = 1)就是可能要改變的軟體數,假設已經有k個被安裝,那麼要改變的軟體數就是deep[x] - k
解除安裝就查詢子樹+自己中有多少已經安裝了的,這個數量就是答案。
每次安裝查詢時都把查詢的點賦為1,解除安裝時把所有涉及到的點賦為0,線段樹維護
1 #include2using
namespace
std;
3#define r register int
4#define ac 120000
5#define ac 600000//
error ...所以說還是陣列小了的鍋麼
6#define d printf("line in %d\n", __line__);
7int
n, m, cnt, ans, w;
8int date[ac], next[ac], head[ac], tot;//
因為是樹,所以只要開這麼大
9int
son[ac], top[ac], father[ac], deep[ac], size[ac], id[ac];
10int tree[ac], l[ac], r[ac], lazy[ac];//
線段樹開4倍吧
11char s[30
];12
13 inline int
read()
1420
21 inline void add(int f, int
w)22
2526
void pre()//
讀入依賴關係, 因為編號從0開始, 所以整體往後順延乙個
2734 deep[1] = 1;35
}36//size包括自己
37void dfs1(int x)//
get son && size && deep
3850 son[x] =maxson;51}
5253
void dfs2(int x, int topx)//
get top && id
5466}67
68void build(int x, int ll, int
rr)69
7677 inline void update(int
x)78
//1 表示 0, 2 表示1,所以用的時候要-1
8586
void search(int x, int ll, int
rr)87
94else95
104}
105}
106107
void change(int x, int ll, int
rr)108
114else
115
124 tree[x] = tree[x * 2] + tree[x * 2 + 1];//
因為是直接修改,而不是加減,所以在這裡修改tree[x]的值
125}
126}
127128
void install(int
x)129
138 printf("
%d\n
", ans);
139}
140141
void uninstall(int
x)142
149150
void work()//
讀入詢問
151165
}166
167int
main()
168
noi2015軟體包管理器
你決定設計你自己的軟體包管理器。不可避免的,你要解決軟體包之間的依賴關係。如果a依賴b,那麼安裝a之前需安裝b,解除安裝b之前須解除安裝a。0號軟體包不依賴任何軟體包。依賴關係不存在環 包括自環 你的任務是,求出每次安裝 刪除操作會改變多少個包的狀態。安裝乙個已安裝的軟體包,或者解除安裝乙個未安裝的...
Noi2015 軟體包管理器
time limit 10 sec memory limit 512 mb 你決定設計你自己的軟體包管理器。不可避免地,你要解決軟體包之間的依賴問題。如果軟體包a依賴軟體包b,那麼安裝軟體包a以前,必須先安裝軟體包b。同時,如果想要解除安裝軟體包b,則必須解除安裝軟體包a。現在你已經獲得了所有的軟體...
NOI2015 軟體包管理器
樹鏈剖分維護。1表示安裝的狀態,0表示沒有安裝的狀態。如果install就是把當前點到根的所有點都變成1,然後計算前後的 delta 如果uninstall呢,就是把自己的子樹變成0,答案也是前後的 delta 具體可以參照 不過我的 常數好大啊,跑得好慢。如下 include include in...