P2146 NOI2015 軟體包管理器

2021-08-29 18:40:54 字數 1496 閱讀 9180

很好的樹剖板子題:

操作一:求點x到0的最短路徑 經過的結點個數-路徑上已安裝的軟體包的總個數,同時將經過的路徑上的所有點標記為已安裝。

操作二:將子樹代表的那段存安裝包個數的區間清空(或者是說將其sum值賦值為0)。

此處為了實現標記已安裝和清空,我們用了乙個標記add:

add[i]=1:線段樹上的點i及其子區間全被賦值為len;

add[i]=2:線段樹上的點i及其子區間全被賦值為0;

這裡add的下放和普通的線段樹下放一樣,原理相同,但注意add值為0時不要pushdown(防止覆蓋子區間原有的add標記)。

**:

#include#include#include#define ri register int

using namespace std;

const int maxn=200020;

int n,m,q,num,u[maxn],v[maxn],fst[maxn],nxt[maxn];

int fa[maxn],deep[maxn],siz[maxn],cmax[maxn],son[maxn],top[maxn],cnt,dfn[maxn];

int l[maxn<<2],r[maxn<<2],sum[maxn<<2],clean[maxn<<2],had[maxn<<2],add[maxn<<2];

string ss;

inline int read()

}void dfs2(int x,int anc)

void pushup(int p)

void pushdown(int p)

if(add[p]==2)

add[p <<1]=add[p],add[p <<1|1]=add[p];

add[p]=0;

}void build(int p,int lft,int rit)

void update(int p,int lft,int rit,int tag)

if(add[p]>0) pushdown(p);

if(lft<=r[p <<1]) update(p <<1,lft,rit,tag);

if(l[p <<1|1]<=rit) update(p <<1|1,lft,rit,tag);

pushup(p);

}int query(int p,int lft,int rit)

int lcau(int x)

tot+=dfn[x]-dfn[top[x]]+1,ans+=query(1,dfn[top[x]],dfn[x]);

update(1,dfn[top[x]],dfn[x],1);

return tot-ans;

}int main()

dfs1(0,0,0);

dfs2(0,0);

build(1,1,n);

q=read();

for(ri i=1;i<=q;i++) }

return 0;

}

P2146 NOI2015 軟體包管理器

輸入格式 從檔案manager.in中讀入資料。輸入檔案的第1行包含1個整數n,表示軟體包的總數。軟體包從0開始編號。隨後一行包含n 1個整數,相鄰整數之間用單個空格隔開,分別表示1,2,3,n 2,n 1號軟體包依賴的軟體包的編號。接下來一行包含1個整數q,表示詢問的總數。之後q行,每行1個詢問。...

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