傳送門
logn
查詢時二分答案,查詢路徑上重鏈中的平衡樹,複雜度
log3n
總複雜度o(
nlogn+
qlog3n
log2n
查詢時把
log 個主席樹放在一起查做到
log2n
(感謝lucida的提醒)
總複雜度o(
nlog2n
+qlog2n)
o(q(
n23logn+
log2n)
) 基本過不了,離線做法
4.整體二分,然後用樹鏈剖分+樹狀陣列維護權值
總複雜度o(
nlogn+
qlog3n
) 常數較小,**複雜度中等,離線做法
(可能有複雜度分析不正確的地方,望指正)
整體二分中的單點修改操作,我用的方法是先減去之前的權值,再加上新的權值,所以修改操作相當於是原先的兩倍
「第k大值」可以在求過lca後變為」求第k小值「
**可讀性不是很高。。。見諒
好像整體二分是可以做到
log2
n 的?算了不管了。。。
**:
#include
#include
#include
using namespace std;
int n,m;
int a[80005],b[110005],ans[30005],dfn[80005],fa[80005],dep[80005],son[80005],siz[80005],top[80005],d[80005];
vectore[80005];
struct optq[140005],l[140005],r[140005];
int in()
void dfs1(intx)}
void dfs2(int
x,int tp)
void add(int
x,int val)
int get(int
x)int cal(int
x,int
y) if (dep[x]y]) swap(x,y);
return t+get(dfn[x])-get(dfn[y]-1);
}int lca(int
x,int
y)void solve(int l,int r,int lo,int ro)
int mid=l+r>>1,lc=0,rc=0;
for (int t,i=lo;i<=ro;++i)
if (q[i].k)
else
for (int i=lo;i<=ro;++i)
if (!q[i].k&&q[i].y
<=mid) add(dfn[q[i].x],-q[i].id);
for (int i=lo;i<=lo+lc-1;++i) q[i]=l[i-lo+1];
for (int i=lo+lc;i<=ro;++i) q[i]=r[i-lo-lc+1];
solve(l,mid,lo,lo+lc-1);
solve(mid+1,r,lo+lc,ro);
}main()
, b[++b[0]]=q[i].y;
for (int u,v,i=1;i1);
dfs2(1,1);
int cnt=0,qq=n;
for (int i=1;i<=m;++i)
;if (q[qq].k)
else
}sort(b+1,b+b[0]+1);
b[0]=unique(b+1,b+b[0]+1)-b-1;
for (int i=1;i<=qq;++i)
if (!q[i].k) q[i].y=lower_bound(b+1,b+b[0]+1,q[i].y)-b;
solve(1,b[0],1,qq);
for (int i=1;i<=cnt;++i)
if (ans[i]==-1) puts("invalid request!");
else
printf("%d\n",ans[i]);
}
bzoj1146 網路管理
發現是鏈上的問題,所以樹鏈剖分 發現要查詢第k大,因為第k大不支援合併,所以要二分答案 二分答案後相當於詢問一些區間內大於某數的數個數,直接線段樹套平衡樹即可 時間複雜度 o nlog n 跟 o n 有什麼區別 可以卡過 1 include2 using namespace std 3 defin...
BZOJ1146 網路管理(主席樹,樹狀陣列)
bzoj許可權題,洛谷題面 樹上帶修改主席樹 貌似和cou nton atre e 那題很相似呀 只需要套上乙個樹狀陣列來維護修改好就好了 但是記住是用df s 來記錄主席樹的標號 一定不要搞錯了 每一次修改只會影響他子數的值 而在d fs序上就是連續的一段 美滋滋的做完了 include incl...
BZOJ1146 CTSC2008 網路管理
樹狀陣列與線段樹 題目傳送門 在尤拉序上用樹狀陣列套權值線段樹搞事情。在進的時候加一,出去的時候減一。從尤拉序第一位到當前點的 l 就是根到當前點的狀態 因為其他的路徑一進一出抵消掉了 然後你求出兩個點的 lca 和 lca 的父親減一減跑一跑就好了。時間複雜度 o nlog 2n 空間複雜度 o ...