Mex(線段樹的巧妙應用)

2022-05-15 23:33:07 字數 2964 閱讀 2289

題目要求求某段區間第乙個沒有出現的數(0,1,2,3.。。。) ,對於所有的區間,我們把這樣的數加起來最後得到乙個結果。

首先,我們要求出這樣的數,然後還得列舉出所有的區間,複雜度太大了。

換種思路,我們定住l,是不是一次效能求出所有的r所得出的結果,這就用到線段樹的性質了,因為在移動l的過程中,移一步只變化乙個數,那麼就可以用線段樹進行維護。

首先求出[1,r] 以1為左端的所有區間的情況,記錄每個點也就是1到那個點的這段區間值sum[i],以這個值建一顆樹,那麼在l向前移動的時候,每次丟掉乙個數a[i-1], 因為少了這乙個數,肯定後面有部分區間是變化的,有部分是不變化的,從這點開始向後找第乙個與a[i-1]值相等的數的位置p,那麼這個位置後面的sum肯定不會變化,因為丟掉的數又補上了。

那麼就可以只考慮,從i位置到p這段裡面的sum,如果原先的sum本來就比a[i-1]小,那說明a[i-1]的減少不影響它的值,所以不用改變,而所有大於a[i-1]的值將都變為a[i-1],這樣更新一下,求和就可以了。

1 #include 2 #include3 #include4 #include5 #include6 #include7 #include8 #include9 #include

10 #include11

using

namespace

std;

12//

#pragma comment(linker, "/stack:1024000000,1024000000")

13#define n 200010

14#define ll __int64

15#define inf 0xfffffff

16const

double eps = 1e-8;17

const

double pi = acos(-1.0

);18

const

double inf = ~0u>>2

;19 vectorpo[n];

20 mapf;

21 ll s[n<<2

];22

int tm[n<<2

];23 ll lz[n<<2

];24

intsum[n];

25int

p[n],a[n];

26bool

vis[n];

27void up(int

w)28

33void down(int w,int

m)3444}

45void build(int l,int r,int

w)46

53int m = (l+r)>>1

;54 build(l,m,w<<1

);55 build(m+1,r,w<<1|1

);56

up(w);57}

58void update(int a,int b,int d,int l,int r,int

w)59

68int m = (l+r)>>1

;69 down(w,r-l+1

);70

if(a<=m) update(a,b,d,l,m,w<<1

);71

if(b>m) update(a,b,d,m+1,r,w<<1|1

);72

up(w);73}

74int find(int k,int l,int r,int

w)75

82int m = (l+r)>>1

;83 down(w,r-l+1

);84

if(tm[w<<1]>k)

85return find(k,l,m,w<<1

);86

else

87return find(k,m+1,r,w<<1|1

);88

}89 ll query(int a,int b,int l,int r,int

w)90

95int m = (l+r)>>1

;96 ll res = 0

;97 down(w,r-l+1

);98

if(a<=m)

99 res+=query(a,b,l,m,w<<1

);100

if(b>m)

101 res+=query(a,b,m+1,r,w<<1|1

);102

return

res;

103}

104int

main()

105122

int o = 0

;123

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

124135

}136 ll ans=0

;137 build(1,n,1

);138 ans+=s[1

];139

//cout<140 p[f[a[1]]] = 1

;141

for(i = 2; i <= n ; i++)

142151

else k =n;

152 update(1,i-1,0,1,n,1

);153

intfk;

154if(tm[1]>a[i-1

])155

159 ans+=query(i,n,1,n,1

);160

//cout<161

//cout<162

//cout<163

//if(a[i]!=a[i-1])

164 p[f[a[i]]]++;

165}

166 cout

167}

168return0;

169 }

view code

區間MEX 線段樹維護mex陣列

問題描述 給你乙個長度為n的數列,元素編號1到n,第i個元素值為ai。現在有m個形如 l,r 的提問,你需要回答出區間 l,r 的mex值。即求出區間 l,r 中沒有出現過的最小的非負整數。輸入格式 第一行,兩個整數n和m 第二行,n個空格間隔的整數,表示數列a 接下來m行,每行兩個整數l,r,表示...

mex(線段樹 離散化)

題目描述 給你乙個無限長的陣列,初始的時候都為0,有3種操作 操作1是把給定區間 l,r l,r l,r 設為1,操作2是把給定區間 l,r l,r l,r 設為0,操作3把給定區間 l,r l,r l,r 0,1反轉。l r 一共n個操作,每次操作後要輸出最小位置的0。l,r 題解 l r 經過分...

poj Buy Tickets 巧妙的線段樹

做完這道題才意識到什麼是線段樹的巧妙運用。yy才是王道啊!include define maxn 200050 define lson l m rt 2 define rson m 1 r rt 2 1 int n int rest maxn 4 ans maxn int id maxn value...