題解 P4688 Ynoi2016 掉進兔子洞

2022-05-02 06:42:14 字數 2924 閱讀 6709

這是我的第一道 ynoi,同時也一發卡到了最優解,發篇題解紀念一下 qwq,不開 $o_2$ 也是能過的。

本題需要的知識點:

- 分塊,莫隊

- $\text$ 優化

- 離散化

- 其它的奇技淫巧

首先明確這題要求的,三個區間內不同時出現的數的個數。列出柿子就是 $(r_1 - l_1 + 1) + (r_2 - l_2 + 1) + (r_3 - l_3 + 1) - rep$,其中 $rep$ 是三個區間內同時出現的數的個數。

首先 $1 \le a_i \le 10^9$,顯然離散化。同時注意,本題離散化時不能去重,即不需要 $\text$,直接使用 $\text\text$ 即可。

隨後對每個詢問求刪除的數,對於這種對多個區間內元素個數的維護我們不難想到莫隊,如莫隊板子題 小 z 的襪子 就是這種題型。

老套路,將長度為 $n$ 的序列拆成 $\sqrt n$ 塊,把所有詢問的區間以 $l$ 為第一關鍵字,$r$ 為第二關鍵字排序。

此時考慮如何求出上文的 $rep$。對每個詢問開乙個長度為 $n$ 的 $\text$,每一位是否為 $1$ 即表示這一位是否被刪除。再維護另乙個 $\text$ $bst$,每一位是否為 $1$ 表示這一區間是否有這個數。則最後要刪除的數就是三個區間的 $bst$ 取交集。

最後要注意,

- 此題 $1 \le n, m \le 10^5$,開不下這麼大的 $\text$,需要分幾次求答案。

- 區間移動位置時,要先加再減。如果先減,則可能會讓 $cnt$ 變成負數再變成正數,會導致 $\text$ 無效訪問記憶體,從而導致 re。

於是這題就結束了,$\text$:

1 #include 2 #include 3 #include 4 #include 5 #include 6 #include 7

#define il inline

8#define rg register910

//namespace io

18//

inline void qread() {}

19//

template

20//

inline void qread(t1 &iee, t2&... ls) while(isdigit(ch = gc()));

27//

__ *= ___;

28//

iee = __;

29//

qread(ls...);

30//

return ;

31//}32

//inline void flush()

37//

inline void putc_(char _x)

41//

inline void qwrite() {}

42//

template

43//

inline void qwrite(t1 iee, t2... ls)

51//

struct flusher_}io_flusher;

52//}53

//54

//using namespace io;

55//

此部分是快讀,為防止抄襲注釋掉了。

56//

注 : 此快讀板子是@spfa(uid=177999) 給我的,為防止他被說是 ctj 特來此宣告一下。

57using

namespace

std;

5859

const

int n = 1e5 + 5;60

const

int m = 25005;61

62 bitsetbst[m], bst;//

bitset 開 25000,分四次求出答案。

63bool

vis[m];

64int

n, m, tot, blocksize;

65int

a[n], b[n], blocknum[n];

66int

ans[n], cnt[n];

6768

struct

node

73 } que[n << 2

];74

75 il void add(int

id)

8081 il void del(int

id)

8687 il void solve(int

k) 99

}100 sort(que + 1, que + tot + 1

);101

bst.reset();

102int l = 1, r = 0

;103

for(rg int i = 1; i <= tot; i++)

112for(rg int i = 1; i <= k; i++) ans[i] -= bst[i].count() * 3

;113

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

%d\n

", ans[i]);

114}

115116

intmain()

124 sort(b + 1, b + n + 1

);125

for(rg int i = 1; i <= n; i++) a[i] = lower_bound(b + 1, b + n + 1, a[i]) - b;//

離散化,不需要去重

126int t = m - 5

;127

while

(m)

132else solve(t), m -=t;

133 }//

分次求出答案

134return0;

135 }

view code

題解 P2016 戰略遊戲

題目 解法跟 dalao real ljs 類似,但沒有用到遞迴 題目相當於需要求覆蓋這顆樹需要的最小點數 用 dp 表示在這棵樹中,以 i 為根節點的子樹在選 不選根節點的情況下,覆蓋這棵樹所有邊需要的最小點數 所以,當不選這個節點 i 時,則所有 以其子節點為根節點的子樹 都必選根節點 當選擇這...

題解 P1712 NOI2016 區間

先按照長度排個序,然後依次新增區間。什麼是新增?設這個區間是 l r l,r 新增就是把al al 1,al 2,a r al,al 1 al 2,ar 都加上1 1 其中ai role presentation style position relative aia i表示第 i i 個位置被幾個...

P4067 SDOI2016 儲能表 題解

給定 n m k p 在模 p 意義下計算 sum sum mathrm i mathrm j k,0 t 組測試 t 5000 n leq 10 m leq 10 k leq 10 p leq 10 9 text 把 sum mathrm a k,0 變為 sum a ge k a sum a g...