题目链接
一、题意
3个序列a,b,c,计算
数据范围:
二、题解
题是真好,我是真菜,这个套路没见过。
考虑枚举,快速统计所有的
对应的答案。
单调队列维护的最大值和最小值,
的最大值和最小值,
的最大值和最小值。
线段树下标 对应的值是
的最大值 - 最小值。
需要开7棵线段树,分别维护序列 。
具体细节还是看代码吧。
三、代码
#include<bits/stdc++.h>
#define pb push_back
#define fi first
#define se second
#define sz(x) (int)x.size()
#define cl(x) x.clear()
#define all(x) x.begin() , x.end()
#define rep(i , x , n) for(int i = x ; i <= n ; i ++)
#define per(i , n , x) for(int i = n ; i >= x ; i --)
#define mem0(x) memset(x , 0 , sizeof(x))
#define mem_1(x) memset(x , -1 , sizeof(x))
#define mem_inf(x) memset(x , 0x3f , sizeof(x))
#define debug(x) cerr << #x << " = " << x << '\n'
#define ddebug(x , y) cerr << #x << " = " << x << " " << #y << " = " << y << '\n'
#define ios std::ios::sync_with_stdio(false) , cin.tie(0)
#define int unsigned int
using namespace std ;
typedef long long ll ;
typedef long double ld ;
typedef pair<int , int> pii ;
typedef pair<ll , ll> pll ;
const int mod = 998244353 ;
const int maxn = 2e5 + 10 ;
const int inf = 0x3f3f3f3f ;
const double eps = 1e-6 ;
mt19937 rnd(chrono::high_resolution_clock::now().time_since_epoch().count()) ;
int n , x[maxn][5] ;
int mx[maxn][5] , p_max[5] ;
int mn[maxn][5] , p_min[5] ;
int ans = 0 ;
struct seg_tree
{
int sum[maxn << 2][10] , add[maxn << 2][10] ;
int ls(int x){ return x << 1 ; }
int rs(int x){ return x << 1 | 1 ; }
void push_up(int p)
{
rep(i , 1 , 7) sum[p][i] = sum[ls(p)][i] + sum[rs(p)][i] ;
}
void f(int id , int len , int k , int op)
{
if(op == 1) // a
{
sum[id][1] += k * len ; // a
sum[id][4] += k * sum[id][2] ; // ab b
sum[id][5] += k * sum[id][3] ; // ac c
sum[id][7] += k * sum[id][6] ; // abc bc
}
else if(op == 2) // b
{
sum[id][2] += k * len ; // b
sum[id][4] += k * sum[id][1] ; // ab a
sum[id][6] += k * sum[id][3] ; // bc c
sum[id][7] += k * sum[id][5] ; // abc ac
}
else // c
{
sum[id][3] += k * len ; // c
sum[id][5] += k * sum[id][1] ; // ac a
sum[id][6] += k * sum[id][2] ; // bc b
sum[id][7] += k * sum[id][4] ; // abc ab
}
add[id][op] += k ;
}
void push_down(int id , int l , int r)
{
int mid = (l + r) >> 1 ;
rep(op , 1 , 3)
if(add[id][op] != 0)
{
f(ls(id) , mid - l + 1 , add[id][op] , op) ;
f(rs(id) , r - mid , add[id][op] , op) ;
add[id][op] = 0 ;
}
}
void update(int id , int l , int r , int x , int y , int k , int op)
{
if(x > y || x > r || y < l) return ; //避免越界。
if(x <= l && r <= y)
{
f(id , r - l + 1 , k , op) ;
return ;
}
push_down(id , l , r) ;
int mid = (l + r) >> 1 ;
if(x <= mid) update(ls(id) , l , mid , x , y , k , op) ;
if(y > mid) update(rs(id) , mid + 1 , r , x , y , k , op) ;
push_up(id) ;
}
} seg ;
signed main()
{
ios ;
cin >> n ;
rep(j , 1 , 3) rep(i , 1 , n) cin >> x[i][j] ;
rep(i , 1 , n)
{
rep(j , 1 , 3)
{
//max
while(p_max[j] >= 1 && x[i][j] >= x[mx[p_max[j]][j]][j])
{
seg.update(1 , 1 , n , mx[p_max[j] - 1][j] + 1 , mx[p_max[j]][j] , -x[mx[p_max[j]][j]][j] , j) ;
p_max[j] -- ;
}
mx[++ p_max[j]][j] = i ;
seg.update(1 , 1 , n , mx[p_max[j] - 1][j] + 1 , mx[p_max[j]][j] , x[mx[p_max[j]][j]][j] , j) ;
//min
while(p_min[j] >= 1 && x[i][j] <= x[mn[p_min[j]][j]][j])
{
seg.update(1 , 1 , n , mn[p_min[j] - 1][j] + 1 , mn[p_min[j]][j] , x[mn[p_min[j]][j]][j] , j) ;
p_min[j] -- ;
}
mn[++ p_min[j]][j] = i ;
seg.update(1 , 1 , n , mn[p_min[j] - 1][j] + 1 , mn[p_min[j]][j] , -x[mn[p_min[j]][j]][j] , j) ;
}
ans += seg.sum[1][7] ;
}
cout << ans << '\n' ;
return 0 ;
}