輸入格式:
從檔案manager.in中讀入資料。
輸入檔案的第1行包含1個整數n,表示軟體包的總數。軟體包從0開始編號。
隨後一行包含n−1個整數,相鄰整數之間用單個空格隔開,分別表示1,2,3,⋯,n−2,n−1號軟體包依賴的軟體包的編號。
接下來一行包含1個整數q,表示詢問的總數。之後q行,每行1個詢問。詢問分為兩種:
install x:表示安裝軟體包x
uninstall x:表示解除安裝軟體包x
你需要維護每個軟體包的安裝狀態,一開始所有的軟體包都處於未安裝狀態。
對於每個操作,你需要輸出這步操作會改變多少個軟體包的安裝狀態,隨後應用這個操作(即改變你維護的安裝狀態)。
輸出格式:
輸出到檔案manager.out中。
輸出檔案包括q行。
輸出檔案的第i行輸出1個整數,為第i步操作中改變安裝狀態的軟體包數。
輸入輸出樣例
輸入樣例#1:複製
7輸出樣例#1:複製0 0 0 1 1 5
5install 5
install 6
uninstall 1
install 4
uninstall 0
313從思路上來看,這個題目不難。23
1、 每次安裝軟體,就把根節點到x軟體路徑上的值全部變為1
同理,每次解除安裝軟體,就把x以及它的子樹的值變為0
2 但是 普通的dfs會超時,只能得分40. 因此需要使用線段樹。
線段樹參考
我的解法 40分。
#include#include#include#include#include#include#include #includeusing namespace std;
#define imax 100000+10
int fa[imax];
vector< vector> ch(imax);
bool ok[imax];
int n;
int q,t;
vectorres;
int dfs(int k)
edge[maxn<<1];
struct node
tree[maxn<<2];
void add(int u,int v)
int read()
void dfs1(int x,int fa,int depth)
}void dfs2(int x,int tp)
}void build(int id,int l,int r)
void downdata(int id)
int get(int id,int l,int r)
void update(int id,int l,int r,int val)
if(tree[id].flag!=-1) downdata(id);
update(id<<1,l,r,val);update(id<<1|1,l,r,val);
tree[id].sum=tree[id<<1].sum+tree[id<<1|1].sum;
return;
}void change(int u,int v,int val)
int main()
dfs1(1,1,1);dfs2(1,1);
q=read();build(1,1,tidnum);
for(int i=1;i<=q;i++)
if(s[0]=='u')
}return 0;
}
P2146 NOI2015 軟體包管理器
很好的樹剖板子題 操作一 求點x到0的最短路徑 經過的結點個數 路徑上已安裝的軟體包的總個數,同時將經過的路徑上的所有點標記為已安裝。操作二 將子樹代表的那段存安裝包個數的區間清空 或者是說將其sum值賦值為0 此處為了實現標記已安裝和清空,我們用了乙個標記add add i 1 線段樹上的點i及其...
P2146 NOI2015 軟體包管理器
p2146 noi2015 軟體包管理器 樹鏈剖分 帶區間修改線段樹 install操作 該點到根之間修改成1 uni操作 該點及其子樹修改成0 每次操作時和上次的相減一下即可 include include include include using namespace std template ...
P2146 NOI2015 軟體包管理器
p2146 noi2015 軟體包管理器 一道樹鏈剖分 還算是比較裸的樹剖w 對於查詢 影響數 的話只需要查詢原本根節點值與現根節點值差異就可以了 include include include include include using namespace std define maxn 1002...