P6503 [COCI2010-2011#3] DIFERENCIJA
moonbowqwq · · 题解
题目链接
题意简述
给出一个长度为
数据范围与约定:
解题思路
显然我们可以把最大值和最小值分别统计,最后把和相减即可,这里我用的是 ST 表。
具体地,假设我们当前所在的区间为
代码实现
#include<bits/stdc++.h>
using namespace std;
int N,A[300005];
class Sparse_Table_Max{
private:
int max_id[300005][20];
int log2(int num){
int res = -1;
while(num > 0)
++res,num >>= 1;
return res;
}
int Max(int a,int b){
if(A[a] > A[b])
return a;
return b;
}
public:
void Init(){
for(int i = 1;i <= N;++i)
max_id[i][0] = i;
for(int k = 1;k < 20;++k)
for(int i = N - (1 << k) + 1;i > 0;--i)
max_id[i][k] = Max(max_id[i][k - 1],max_id[i + (1 << k - 1)][k - 1]);
return;
}
int Query(int l,int r){
int k = log2(r - l + 1);
return Max(max_id[l][k],max_id[r - (1 << k) + 1][k]);
}
}STX;
class Sparse_Table_Min{
private:
int min_id[300005][20];
int log2(int num){
int res = -1;
while(num > 0)
++res,num >>= 1;
return res;
}
int Min(int a,int b){
if(A[a] < A[b])
return a;
return b;
}
public:
void Init(){
for(int i = 1;i <= N;++i)
min_id[i][0] = i;
for(int k = 1;k < 20;++k)
for(int i = N - (1 << k) + 1;i > 0;--i)
min_id[i][k] = Min(min_id[i][k - 1],min_id[i + (1 << k - 1)][k - 1]);
return;
}
int Query(int l,int r){
int k = log2(r - l + 1);
return Min(min_id[l][k],min_id[r - (1 << k) + 1][k]);
}
}STN;
__int128 DFS1(int l,int r);
__int128 DFS2(int l,int r);
int main(){
scanf("%d",&N);
for(int i = 1;i <= N;++i)
scanf("%d",&A[i]);
STN.Init(),STX.Init();
printf("%lld",(long long)(DFS1(1,N) - DFS2(1,N)));
return 0;
}
__int128 DFS1(int l,int r){
if(l > r)
return 0;
if(l == r)
return A[l];
int mid = STX.Query(l,r);
return (__int128)(mid - l + 1) * (r - mid + 1) * A[mid] + DFS1(l,mid - 1) + DFS1(mid + 1,r);
}//get max
__int128 DFS2(int l,int r){
if(l > r)
return 0;
if(l == r)
return A[l];
int mid = STN.Query(l,r);
return (__int128)(mid - l + 1) * (r - mid + 1) * A[mid] + DFS2(l,mid - 1) + DFS2(mid + 1,r);
}//get min