JXOI2017 顏色 線段樹求點對貢獻

2022-05-13 16:58:51 字數 2503 閱讀 8381

可憐有乙個長度為 n 的正整數序列 ai,其中相同的正整數代表著相同的顏色。

現在可憐覺得這個序列太長了,於是她決定選擇一些顏色把這些顏色的所有位置都刪去。

刪除顏色 i 可以定義為把所有滿足 aj = i 的位置 j 都從序列中刪去。

然而有些時候刪去之後,整個序列變成了好幾段,可憐不喜歡這樣,於是她想要知道有多少種刪去顏色的方案使得最後剩下來的序列非空且連續。

例如顏色序列 ,刪除顏色 3 後序列變成了 和 兩段,不滿足條件。而刪除顏色 1 後序列變成了 ,滿足條件。

兩個方案不同當且僅當至少存在乙個顏色 i 只在其中乙個方案中被刪去。

輸入格式:

第一行輸入乙個整數 t 表示資料組數。每組資料第一行輸入乙個整數 n 表示數列長度。第二行輸入 n 個整數描述顏色序列。

輸出格式:

對於每組資料輸出乙個整數表示答案。

輸入樣例#1:複製

1

51 3 2 4 3

輸出樣例#1:複製

6
滿足條件的刪顏色方案有 , , , , , ∅.

對於 20% 的資料,保證 1 ≤∑n ≤ 20。

對於 40% 的資料,保證 1 ≤∑n ≤ 500。

對於 60% 的資料,保證 1 ≤∑n ≤ 10^4。

對於 100% 的資料,保證 1 ≤ t,∑n ≤ 3 × 10^5, 1 ≤ ai ≤ n。

每段合法區間都是連續的,自然而然會想到列舉乙個端點,然後求另乙個端點的合法個數。

感覺這個套路比較常見,但是我依然不會。

我們可以先列舉右端點,然後怎麼確定左端點的個數呢,感覺很麻煩是不是,正難則反嘛。

定義a[i]為i點的值,head[a[i]]為a[i]最左端點的位置,tail[i]為其最右端的位置。

列舉右端點,當右端點為第i位,令r=i,假設存在乙個l,使得區間(l,r)為合法區間,

對於j(l<=j<=r),滿足:

1.tail[a[j]]<=r

2.head[a[j]]>=l

到這一步接下來就有點難想到了。

對於每個點i,如果i=tail[a[i]],那麼對於任何區間,head[a[i]]+1~tail[a[i]]不可能是左端點,我們將這段區間賦值成一。

再找到最靠近i的k滿足,tail[k]>i,則(1,k)之間不可能存在左端點。

i為右端點的貢獻等於,i-k-sum[k+1,i](sum[k+1,i]為k+1到i的被標記了的總和,藍字部分).

至於怎麼找k,可以用單調棧來維護,因為彈出棧的話,就不會再用到了。

1 #include2

using

namespace

std;

3#define ll long long

4#define n 50005056

intn,top,a[n],sk[n];

7int

head[n],tail[n],last[n],nex[n];

8struct tree tr[n<<2

];9 templatevoid read(t&x)

1018

void read_char(char &c)

19 20

void push_up(int

x)21

28void push_down(int

x)29

37void bt(int x,int l,int

r)38;40

if (l==r) return;41

int mid=(l+r)>>1

;42 bt(x<<1

,l,mid);

43 bt(x<<1|1,mid+1

,r);44}

45void update(int x,int l,int

r)46

54int mid=(tr[x].l+tr[x].r)>>1;55

push_down(x);

56if (l<=mid)update(x<<1

,l,r);

57if (mid1|1

,l,r);

58push_up(x);59}

60int query(int x,int l,int

r)61

71void

work()

7282 bt(1,1

,n);

83 sk[top=0]=0

;84 tail[0]=n+1

;85 ll ans=0;86

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

8796

}97 printf("

%lld\n

",ans);98}

99void

clear()

100104

intmain()

105116 }

view code

Sdoi2017 樹點塗色 lct 線段樹

題意 一棵有根樹,支援x到根染成新顏色,求x到y顏色數,求x子樹裡點到根顏色數最大值 考場發現這個資訊是可減的,但是沒想到lct 特意設計成lct的形式!如何求顏色數?維護乙個點和父親的顏色是否一樣,不一樣為1,就是字首和。考慮相鄰的思想和那道 水位線 有點像 x到y的答案就是 s x s y 2 ...

SDOI2017 樹點塗色 LCT 線段樹

可以發現更新操作就是 text 的 text 操作,這個操作複雜度是 o n log n 的 因此,考慮對於每次的 text 操作,維護每個點到根的路徑上不同的權值個數 每次 text 操作只設計到合併兩個鏈 斷開一條鏈兩種操作,可以通過線段樹維護子樹修改 那麼修改的複雜度就是 o n log 2 ...

SDOI2017 樹點塗色(LCT 線段樹)

給你一棵以 1 為根,有 n 個節點的樹,初始時每個節點的顏色互不相同,記一條路徑的權值為這條路徑 包括起點和終點 上所有不同的顏色個數,一共 m 個操作,每次支援以下 3 種操作之一 把點 x 到根節點的路徑上所有的點染上一種沒有用過的新顏色 求 x 到 y 的路徑的權值 在以 x 為根的子樹中選...