牛客挑戰賽32 E 樹上逆序對

2022-08-21 03:15:10 字數 1236 閱讀 5014

對於一對 $(x, y)$,能成為逆序對的取決於絕對值大的那個數的符號。

假如 $a[x] > a[y]$,當 $a[x]$ 為正時,不管 $a[y]$ 取不取負號都比 $a[x]$ 小。

當 $a[x]$ 為負時, 不管 $a[y]$ 取不取負號都比 $a[x]$ 大。

那麼就變成了統計每個節點的子樹及祖先有多少個比它的權值小的。取正時,子樹內權值比它小的節點對答案有貢獻,取負時,祖先中權值比它的節點對答案有貢獻。

然後就相當於01揹包了。

用bitset優化一下複雜度就是 $o(\dfrac)$

求子樹內和到根的路徑上比該節點小的數可以樹剖做。但看了tangjz的**發現乙個更加巧妙的方法。

求子樹內顯然可以從小到大插入節點+dfs序+樹狀陣列。

求該節點到根的路徑上比自己權值大的,就相當於求自己有幾個祖先,相當於求自己在多少個節點的子樹內。

那麼多開乙個樹狀陣列,在插入乙個節點時,讓其子樹這個區間(不包括自身)區間加一。查詢時單點查值就行了。

#include using

namespace

std;

const

int n = 1e5 + 7

;bitset

<30001>mask;

intn;

struct

bit

void add(int x, int

v)

int query(int

x) } bit[2];

int a[n], in[n], out

[n], tol, o[n];

vector

g[n];

void dfs(int u, int

fa)

bool cmp(const

int &x, const

int &y)

intmain()

sort(o + 1, o + n + 1

, cmp);

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

dfs(

1, -1

); mask.

set(0

);

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

intq;

scanf("%d

", &q);

while (q--)

return0;

}

view code

牛客挑戰賽58

前i 1的二進位制相等,a的前n個數的前i 1位可以亂取,b的前n 1個數前i 1位也可以亂取,因為b的第n個數的前i 1異或可為任意值,所以sum1 2 i 1 n 2 i 1 n 1 2 i 1 2n 1 a的第i位為1且b的第i位為0 只要a的n數第i位中有乙個不為0的,a的第i位不為0,b的...

牛客挑戰賽45 E 旁觀者

構造乙個 n 個點,m 條邊的仙人掌,使得隨機刪 k 個點之後期望的連通塊個數盡量大。輸出這個最大的期望的連通塊數。n,m,k le 10 9 神仙題。我的1h 考慮正難則反,最終 連通塊數 點數 邊數 環數 點數和邊數可以算,於是我們希望最大化最終剩下的期望環數。這時候可以感覺到欽定每個環長度為 ...

牛客網wannafly挑戰賽13 E 線段樹

時間限制 c c 1秒,其他語言2秒 空間限制 c c 262144k,其他語言524288k 64bit io format lld vvq 最近迷上了線段這種東西 現在他手上有 n 條線段,他希望在其中找到兩條有公共點的線段,使得他們的異或值最大。定義線段的異或值為它們並的長度減他們交的長度 第...