【題目鏈結】
【題解】
按dfs序樹分塊的模板題。
每個節點的子樹在dfs序中一定為一串連續的區間,那我們對dfs序分塊就行了,每個塊內元素按大小排序。查詢時暴力找邊界上的塊,中間的塊二分一下。修改時暴力維護大小順序,插入時插在它的父親後(dfs序為它的父親+1),然後暴力修改當前塊的dfs序。
複雜度o(n
n−−√
logn
) o(n
nlog
n)
可以修改塊的大小使複雜度更優。
/* --------------
user vanisher
problem bzoj-3720
----------------*/
# include # define ll long long
# define inf 0x3f3f3f3f
# define n 60010
# define k 1001
using namespace std;
int read()
while (ch>='0'&&ch<='9')
return tmp*fh;
}struct edgee[n*2];
struct nodek[k][k];
int w[n],nex[k],n,t,now,kdep[k],num,size[k],dep[n],nowdep,p[n],dad[n],head[n],place;
bool cmpw(node x, node y)
void dfs(int x, int fa)
k[num][++now]=; p[x]=num; dad[x]=fa;
dep[x]=dep[fa]+1, nowdep=min(dep[x],nowdep);
for (int ed=head[x]; ed!=0; ed=e[ed].next)
if (e[ed].data!=fa)
dfs(e[ed].data,x);
}int query(int x, int y)
ans=ans+size[ed]+1-now;
} l=1, r=size[ed];
for (int i=1; i<=size[ed]; i++)
if (dep[k[ed][i].id]<=dep[x])
r=min(r,k[ed][i].p-1);
for (int i=1; i<=size[ed]; i++)
if (k[ed][i].p>=l&&k[ed][i].p<=r)
if (w[k[ed][i].id]>y) ans++;
return ans;
}void modify(int x, int y)
} void cut(int x)
sort(k[x]+1,k[x]+size[x]+1,cmpw);
sort(k[num]+1,k[num]+size[num]+1,cmpw);
}void extend(int x, int y); p[n]=p[x];
for (int j=size[p[x]]-1; j>0&&w[k[p[x]][j].id]>w[k[p[x]][j+1].id]; j--)
swap(k[p[x]][j],k[p[x]][j+1]);
if (size[p[x]]>=2
*t) cut(p[x]);
return;
}}int main()
if (opt==1) modify(x,w);
if (opt==2) extend(x,w);
}return
0;}
bzoj3720 Gty的妹子樹
我們可以樹上分塊,詳見我部落格中雜文下的根號演算法題庫 然後每個塊維護降序,對於整一塊在子樹內的就可以二分,其餘部分暴力。include include include include define fo i,a,b for i a i b i using namespace std const i...
BZOJ3720 Gty的妹子樹
如果沒有插入操作,那麼直接對dfs序建立線段樹套平衡樹即可,有插入操作的話,將外層的線段樹換成重量平衡樹即可。一開始寫替罪羊樹套權值線段樹無限mle 所以只好寫替罪羊樹套treap include include includeusing namespace std typedef unsigned...
BZOJ3720 Gty的妹子樹
題目 題解 傳說中的塊狀樹。和鏈剖思想差不多,能塞到父親塊裡的就塞,否則自己新開一塊。只是比較糾結樹分塊究竟用什麼?如果是樹上莫隊的話好像不能這麼分?被菊花卡死?然後我們就每個塊暴力維護資訊。剛開始以為set就行了,到了寫查詢的時候發現尼瑪set是不能維護名次的t t 還是老老實實寫線性表吧。塊開s...