用樹剖搞出dfs序,這樣能把一棵子樹變成乙個區間,一條鏈變成log個區間。
用線段樹維護一段連續的dfs序中有幾個點。共兩種操作:
第乙個加點,將log個區間中的總點數統計出來,然後填滿,答案為∑(區間長度-原有點數),複雜度o(n(logn)^2)
第二個刪點,把一段區間中的總點數統計出來作為答案,然後全部清空。複雜度o(nlogn)
因為bzoj的時限放到了10秒,所以是可以過的。
**:
#include#includeusing namespace std;
#define rep(i,j,k) for(i=j;i<=k;++i)
#define per(i,j,k) for(i=j;i>=k;--i)
const int n=100005;
int n,m,ans;
int ne[n<<1],he[n],to[n<<1],tot;
int pre[n],son[n],dad[n],dep[n],sz[n],dfn[n],cnt;
int t[n<<2],lz[n<<2];
void add(int x,int y)
void dfs1(int x)
}void dfs2(int x)
void pd(int l,int r,int num)
}void up(int l,int r,int mid,int num)
int ins(int l,int r,int l,int r,int num)
int mid=l+r>>1,tmp=t[num];
if(l<=mid)ins(l,r,l,mid,num<<1);
if(r>mid)ins(l,r,mid+1,r,num<<1|1);
up(l,r,mid,num);
return t[num]-tmp;
}int del(int l,int r,int l,int r,int num)
int mid=l+r>>1,tmp=t[num];
if(l<=mid)del(l,r,l,mid,num<<1);
if(r>mid)del(l,r,mid+1,r,num<<1|1);
up(l,r,mid,num);
return tmp-t[num];
}int main()
dfs1(1);dfs2(1);
scanf("%d",&m);
memset(lz,-1,sizeof lz);
while(m--)
else ans=del(dfn[x],dfn[x]+sz[x]-1,1,n,1);
printf("%d\n",ans);
} return 0;
}
bzoj4196 NOI2015 軟體包管理器
time limit 10 sec memory limit 512 mb submit 1168 solved 672 你決定設計你自己的軟體包管理器。不可避免地,你要解決軟體包之間的依賴問題。如果軟體包a依賴軟體包b,那麼安裝軟體包a以前,必須先安裝軟體包b。同時,如果想要解除安裝軟體包b,則必...
bzoj 4196 Noi2015 軟體包管理器
你決定設計你自己的軟體包管理器。不可避免地,你要解決軟體包之間的依賴問題。如果軟體包a依賴軟體包b,那麼安裝軟體包a以前,必須先安裝軟體包b。同時,如果想要解除安裝軟體包b,則必須解除安裝軟體包a。現在你已經獲得了所有的軟體包之間的依賴關係。而且,由於你之前的工作,除0號軟體包以外,在你的管理器當中...
bzoj4196 Noi2015 軟體包管理器
題目大意 有一棵樹,兩個修改 install x 把根節點到 x 軟體路徑上的值全部變為 1 並輸出修改的節點個數 uninstall x 把 x 以及它的子樹的值變為 0 並輸出修改的節點個數 題解 樹鏈剖分,比較一下修改前後值的變化,即為答案 卡點 1.邊忘記開兩倍 c code include...