題目描述見鏈結 .
直接使用莫隊, 但是這道題目刪除時不好尋找次大值, 考慮回滾莫隊,
回滾莫隊的處理方式與莫隊大致是相同的, 具體來說
對兩個相鄰的詢問區間 [l′
,r′]
,[l,
r]
[l',r'], \ \ [l, r]
[l′,r′
],[l
,r],
若 b k_
id[l
]=bk
_id[
r]
bk\_id[l] = bk\_id[r]
bk_id[
l]=b
k_id
[r], 直接 o(n
)o(\sqrt)
o(n
) 暴力求解 .
若 b k_
id[l
′]≠b
k_id
[l
]bk\_id[l'] \not= bk\_id[l]
bk_id[
l′]
=bk
_id[
l], 暴力將左端點和右端點移動到 l+1
,l
l+1, l
l+1,l .
若 b k_
id[l
′]=b
k_id
[l
]bk\_id[l'] = bk\_id[l]
bk_id[
l′]=
bk_i
d[l]
, 暴力處理左端點對答案的貢獻, 處理完將左端點歸位,
由於右端點是有序的, 可以直接將右端點從 r′r'
r′移動到 r
rr, 無需歸位,
每個塊移動右端點 o(n
)o(n)
o(n)
次, 複雜度 o(n
n)
o(n\sqrt)
o(nn)
.
#include
#define reg register
typedef
long
long ll;
intread()
while
(isdigit
(c)) s = s*
10+ c-
'0', c =
getchar()
;return s * flag;
}const
int maxn =
1e5+5;
int n;
int q_;
int len;
int bkcnt;
int a[maxn]
;int b[maxn]
;int llim[maxn]
;int rlim[maxn]
;int bkid[maxn]
;int tong[maxn]
;int tong2[maxn]
;ll ans;
ll res[maxn]
;struct que que[maxn]
;bool
cmp(que a, que b)
void
add(
const
int&x)
void
del(
const
int&x)
void
write
(ll x)
intmain()
std::
sort
(que+
1, que+q_+
1, cmp)
;int lt =
1, rt =
0, last =0;
for(reg int i =
1; i <= q_; i ++)if
(last != bkid[que[i]
.l])
while
(rt < que[i]
.r)add
(++ rt)
; ll tmp = ans;
while
(lt > que[i]
.l)add
(-- lt)
; res[que[i]
.id]
= ans;
while
(lt < rlim[bkid[que[i]
.l]]+1
)del
(lt ++
); ans = tmp;
}for
(reg int i =
1; i <= q_; i ++
)return0;
}
回滾莫隊 AT1219 歴史 研究
洛谷題目 at1219 不滿足區間減性質的運算,如最值,就不能用普通莫隊求,考慮回滾莫隊,它的核心思想就是若區間在塊內直接暴力,否則將右端點從小到大排序,右端點按普通莫隊求,那麼左端點由於只在乙個塊內,所以詢問完跳到塊末,由於塊的大小為根號,影響複雜度的實際上是右端點,然後每次處理完相同左端點塊清除...
AT1219 歴史 研究(回滾莫隊模板)
點此看題面 這種區間詢問的問題一般來說可以利用莫隊解決。然而這道題求的是最大值,似乎普通莫隊就無法很好地實現刪除操作,因此就需要回滾莫隊這種黑科技。考慮我們先暴力處理掉左端點和右端點在同乙個塊內的詢問 顯然這部分複雜度是 o n sqrt n 的 然後對於剩餘的詢問把它扔到左端點對應塊的 vecto...
題解 AT1219 歴史 研究
簡單分析 題面含有ioi 驚 可知此題是ioi 數字三角形 難度 逃 當然很多人都是抱著學回滾莫隊的目標來看這道題的,所以這裡介紹一下回滾莫隊。1 按莫隊的思路講詢問排序。2 查詢時列舉每個區間,我們需要保證右端點是保持單調遞增的,同時左端點每次在乙個塊中移動,以此來計算每個詢問的值。3 每一次到下...