ABC470G
这个扫描线感觉挺板的吧。
一些定义
定义
定义
正确解法
这种对于所有区间统计的,大部分都可以往扫描线去靠。
先预处理出
这其实就是删掉了最开头的一个元素。实际上,我们要考虑的就是这个元素的贡献。
对于
那具体的,对于哪些
那做法就很明了了,其实我们刚才说的就相当于对
注意到
AC Code
#include<bits/stdc++.h>
#define int long long
using namespace std ;
const int MAXN = 3e5 + 7 ;
int a[MAXN] ;
int val[MAXN] ;
struct SegmentTree {
int mx[4 * MAXN] ;
int sum[4 * MAXN] ;
int lan[4 * MAXN] ;
void push_up(int u) {
mx[u] = max(mx[u * 2] , mx[u * 2 + 1]) ;
sum[u] = sum[u * 2] + sum[u * 2 + 1] ;
}
void BuildTree(int u , int l , int r) {
lan[u] = -1 ;
if (l == r) {
mx[u] = sum[u] = val[l] ;
return ;
}
int mid = (l + r) >> 1 ;
BuildTree(u * 2 , l , mid) ;
BuildTree(u * 2 + 1 , mid + 1 , r) ;
push_up(u) ;
}
void push_down(int u , int l , int r) {
if (lan[u] == -1) return ;
int mid = (l + r) >> 1 ;
lan[u * 2] = lan[u * 2 + 1] = mx[u * 2] = mx[u * 2 + 1] = lan[u] ;
sum[u * 2] = lan[u] * (mid - l + 1) ;
sum[u * 2 + 1] = lan[u] * (r - mid) ;
lan[u] = -1 ;
return ;
}
int Binary(int u , int l , int r , int val) {
if (l == r) return l ;
push_down(u , l , r) ;
int mid = (l + r) >> 1 ;
if (mx[u * 2] >= val) {
return Binary(u * 2 , l , mid , val) ;
}
else {
return Binary(u * 2 + 1 , mid + 1 , r , val) ;
}
}
void Change(int u , int l , int r , int gl , int gr , int val) {
if (gl <= l and r <= gr) {
lan[u] = mx[u] = val ;
sum[u] = val * (r - l + 1) ;
return ;
}
push_down(u , l , r) ;
int mid = (l + r) >> 1 ;
if (mid >= gl) Change(u * 2 , l , mid , gl , gr , val) ;
if (mid + 1 <= gr) Change(u * 2 + 1 , mid + 1 , r , gl , gr , val) ;
push_up(u) ;
return ;
}
int Query(int u , int l , int r , int gl , int gr) {
if (gl <= l and r <= gr) {
return sum[u] ;
}
push_down(u , l , r) ;
int mid = (l + r) >> 1 ;
int ans = 0 ;
if (mid >= gl) ans += Query(u * 2 , l , mid , gl , gr) ;
if (mid + 1 <= gr) ans += Query(u * 2 + 1 , mid + 1 , r , gl , gr) ;
return ans ;
}
}g;
struct DSU {
int fa[MAXN] ;
void Init(int n) {
for (int i = 0 ; i <= n + 1 ; i ++) {
fa[i] = i ;
}
}
int get_fa(int u) {
if (fa[u] == u) return u ;
return fa[u] = get_fa(fa[u]) ;
}
void merge(int u , int v) {
int Fau = get_fa(u) , Fav = get_fa(v) ;
if (Fau == Fav) return ;
fa[Fau] = Fav ;
return ;
}
}o;
int nxt[MAXN] ;
int lst[MAXN] ;
signed main()
{
// freopen("" , "r" , stdin) ;
// freopen("" , "w" , stdout) ;
ios::sync_with_stdio(0) ;
cin.tie(0) ;
cout.tie(0) ;
int n ;
cin >> n ;
o.Init(n) ;
for (int i = 1 ; i <= n ; i ++) {
cin >> a[i] ;
if (lst[a[i]] != 0) {
nxt[lst[a[i]]] = i ;
}
lst[a[i]] = i ;
o.merge(a[i] , a[i] + 1) ;
val[i] = o.get_fa(0) ;
}
for (int i = 1 ; i <= n ; i ++) {
if (!nxt[i]) {
nxt[i] = n + 1 ;
}
}
g.BuildTree(1 , 1 , n) ;
int ans = 0 ;
for (int i = 1 ; i <= n ; i ++) {
ans += g.Query(1 , 1 , n , i , n) ;
int dir = g.Binary(1 , 1 , n , a[i] + 1) ;
int val = g.Query(1 , 1 , n , dir , dir) ;
if (val > a[i])
g.Change(1 , 1 , n , dir , nxt[i] - 1 , a[i]) ;
}
cout << ans ;
return 0 ;
}