【题解】Luogu P10173 「OICon-02」maxiMINImax
容易发现相交的区间是不会产生贡献的。于是不用考虑这个限制。
用单调栈可以求出以 \(a_i\) 为最小值和最大值的区间个数 \(qmn_i\) 和 \(qmx_i\)。
从小到大枚举第二个区间的最小值,记 \(p_i\) 表示 \(i\) 的位置,则对于 \(i\) 的答案即为:
\[\sum_{j=1}^{p_i-1}\sum_{k=p_i+1}^{n}{qmn_{p_i}qmx_jqmx_k(i-a_j)(i-a_k)}
\]
简单推式子后得到:
\( qmn_{p_i}(\sum{qmx_j}\sum{qmx_k}i^2-\sum{qmx_ja_j}\sum{qmx_k}i-\sum{qmx_j}\sum{qmx_ka_k}i+\sum{qmx_ja_j}\sum{qmx_ka_k}) \)
于是开两棵树状数组维护 \(qmx_j\) 和 \(qmx_ja_j\) 就好了。时间复杂度 \(O(n\log n)\)。
复制代码
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
using namespace std;
namespace asbt{
namespace cplx{bool begin;}
const int maxn=1e6+5,mod=9712176;
int n,a[maxn],p[maxn],zhan[maxn];
int lmn[maxn],rmn[maxn];
int lmx[maxn],rmx[maxn];
int qmn[maxn],qmx[maxn];
struct{
int tr[maxn];
il int lowbit(int x){
return x&-x;
}
il void upd(int p,int v){
for(;p<=n;p+=lowbit(p)){
(tr[p]+=v)%=mod;
}
}
il int query(int p){
int res=0;
for(;p;p-=lowbit(p)){
(res+=tr[p])%=mod;
}
return res;
}
il int query(int l,int r){
return (query(r)-query(l-1)+mod)%mod;
}
}F1,F2;
namespace cplx{
bool end;
il double usdmem(){return (&begin-&end)/1048576.0;}
}
int main(){
ios::sync_with_stdio(0),cin.tie(0);
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
p[a[i]]=i;
}
for(int i=1,top=0;i<=n;i++){
while(top&&a[zhan[top]]>a[i]){
top--;
}
lmn[i]=zhan[top];
zhan[++top]=i;
}
for(int i=1,top=0;i<=n;i++){
while(top&&a[zhan[top]]<a[i]){
top--;
}
lmx[i]=zhan[top];
zhan[++top]=i;
}
zhan[0]=n+1;
for(int i=n,top=0;i;i--){
while(top&&a[zhan[top]]>a[i]){
top--;
}
rmn[i]=zhan[top];
zhan[++top]=i;
}
for(int i=n,top=0;i;i--){
while(top&&a[zhan[top]]<a[i]){
top--;
}
rmx[i]=zhan[top];
zhan[++top]=i;
}
for(int i=1;i<=n;i++){
qmn[i]=(i-lmn[i])*1ll*(rmn[i]-i)%mod;
qmx[i]=(i-lmx[i])*1ll*(rmx[i]-i)%mod;
}
int ans=0;
for(int i=1,xj,xaj,xk,xak;i<=n;i++){
xj=F1.query(1,p[i]-1);
xaj=F2.query(1,p[i]-1);
xk=F1.query(p[i]+1,n);
xak=F2.query(p[i]+1,n);
(ans+=qmn[p[i]]*1ll*(xj*1ll*xk%mod*i%mod*i%mod-xaj*1ll*xk%mod*i%mod-xj*1ll*xak%mod*i%mod+xaj*1ll*xak%mod)%mod)%=mod;
(ans+=mod)%=mod;
F1.upd(p[i],qmx[p[i]]);
F2.upd(p[i],qmx[p[i]]*1ll*i%mod);
}
cout<<ans;
return 0;
}
}
int main(){return asbt::main();}
分类:
题解类
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步