luogu5654 基礎函式練習題

2022-06-07 09:21:12 字數 2347 閱讀 3632

答案即區間$[l,r]$的笛卡爾樹上,左右子樹有乙個為空的點到根路徑和(定義此為的該點答案)的max,

對求區間笛卡爾樹複雜度為$o(n)$,無法通過,因此在全域性笛卡爾樹中考慮此問題

設$k$為$l$和$r$的lca,那麼$i$的答案就是$i$到$k$路徑中在$[l,r]$中的部分的和

對於$i$所在子樹分類,即將$[l,r]$分為$[l,k)$和$(k,r]$兩部分(分別求max),以下以左半部分為例:

考慮$i$到$k$的鏈,由於$i$在$k$左子樹中,因此這條鏈也時刻在$k$左子樹中,即其一定在$k$也就是$r$的左邊,因此只需要考慮這個位置大於等於$l$

進一步的,再求$l$和$i$的lca(記為$j$),由於是lca且$l\le i$,因此$l$一定在$j$的左子樹中,$i$在$j$的右子樹中,因此$i$到$j$的這一部分一定都在$l$的右邊,換言之可以列舉lca,直接對右子樹內所有點深度取max

還要考慮$j$到$k$的部分,即求這一部分中在$l$右邊的數之和,這件事是與$l$無關而僅和$j$本身有關,凡是這條鏈上其兒子是其右兒子的都不能被計算

(因為這就說明了$k$在其右子樹,$l$又在$k$子樹內,即$l$在其的右邊,反之就說明$l$在左邊)

根據上面的性質,具體過程如下——

預處理出以下三個陣列:$s_[k]$表示$k$到根路徑中所有點的和,$s_[k]$表示其中所有兒子是左兒子的點之和(特別的,$k$都計算入內),$mx[k]$表示$k$子樹中滿足左右子樹有乙個為空的點的$s_[k]$的最大值

考慮詢問$[l,k)$,暴力列舉$j$,則對於給定的$j$,其對答案的貢獻為$mx[rs[j]]-s_[j]+s_[j]-s_[k]+w[k]$(注意$j$一定在$l$的右邊,否則不可能是$l$和$i$的lca),貢獻是取max

離線,將詢問掛在$l$上,然後遍歷笛卡爾樹,對於點$k$,將$mx[rs[k]]-s_[k]+s_[k]$記在以$k$的深度為下標的線段樹上,然後搜尋左子樹,當搜尋右子樹時撤銷此記錄

(右半部分類似,即只考慮其兒子是右兒子的點)

注意要開long long,時間複雜度為$o(n\log_n)$,可以通過

1 #include2

using

namespace

std;

3#define n 500005

4#define ll long long

5#define l (k<<1)

6#define r (l+1)

7#define mid (l+r>>1)

8 vectorint,int> >vl[n],vr[n];

9int n,q,x,y,a[n],w[n],st[n],ls[n],rs[n],s[n],f[n][21

];10 ll s1[n],s2[n],s3[n],mx[n],ans[n],tr[n<<2

]; 11

int lca(int x,int

y)21

return f[x][0

];22}23

void dfs(int k,int

fa)38

void update(int k,int l,int r,int

x,ll y)

43if (x<=mid)update(l,l,mid,x,y);

44else update(r,mid+1

,r,x,y);

45 tr[k]=max(tr[l],tr[r]);46}

47 ll query(int k,int l,int r,int x,int

y)52

void calc_l(int

k)60

calc_l(ls[k]);

61 update(1,1,n,s[k],-1e15);

62calc_l(rs[k]);63}

64void calc_r(int

k)72

calc_r(rs[k]);

73 update(1,1,n,s[k],-1e15);

74calc_r(ls[k]);75}

76int

main()

85 mx[0]=-1e15;

86 dfs(st[1],0

);87

for(int i=1;i<=q;i++)

94for(int i=1;i<=n;i++)update(1,1,n,i,-1e15);

95 calc_l(st[1

]);96 calc_r(st[1

]);97

for(int i=1;i<=q;i++)printf("

%lld\n

",ans[i]);

98 }

view code

luogu5651 基礎最短路練習題 ?

開始只是打了個暴力 然後陣列大小開錯re了 然後就沒管了頹廢去了 果然還是水題坐著舒服 題目保證不存在簡單環使得邊權異或和不為0 即所有環的權值異或和都為0 那麼隨便在那個點拆開的話斷開的這兩條路上的權值異或和都相同 所以就把環斷開 將其變成一顆樹 然後搞做 int tot 0,head n str...

C 友元函式基礎練習

include includeusing namespace std 定義time類 資料成員 m ihour,m iminute,m isecond 成員函式 建構函式 友元類 watch class time private int m ihour int m iminute int m ise...

6 Python基礎 函式練習

1.設計乙個函式,統計乙個字串中出現頻率最高的字元 單個符號 及其出現次數 定義函式 def str max count2 my str if len my str 1 print 輸入錯誤!return my dic for item in my str my dic.update max cou...