[ 决策单调性 分治 ] LOJ#535 花火

题解

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
inline char nc() {
    static char buf[100000],*p1=buf,*p2=buf;
    return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
inline void Read(int& x) {
    char c=nc();
    for(;c<'0'||c>'9';c=nc());
    for(x=0;c>='0'&&c<='9';x=(x<<3)+(x<<1)+c-48,c=nc());
}
const int N=300010;
const int M=7000000;
int k,n,m,x;
int a[N];
int Rt[N],c[M],ls[M],rs[M],num;
int s[N];
int b[N],d[N],l1,l2;
int Ans;
ll sum;
void Update(int& x,int y,int l,int r,int z) {
    x=++num;
    c[x]=c[y]+1;
    if(l==r)return;
    int Mid=l+r>>1;
    if(z<=Mid) rs[x]=rs[y],Update(ls[x],ls[y],l,Mid,z);
        else ls[x]=ls[y],Update(rs[x],rs[y],Mid+1,r,z);
}
int Query(int x,int y,int l,int r,int L,int R) {
    if(l>R||r<L) return 0;
    if(l>=L&&r<=R) return c[y]-c[x];
    int Mid=l+r>>1;
    return Query(ls[x],ls[y],l,Mid,L,R)+Query(rs[x],rs[y],Mid+1,r,L,R);
}
int Get(int l,int r) {
    return Query(Rt[l],Rt[r-1],1,n,a[r],a[l])+Query(Rt[l],Rt[r-1],1,n,a[r],a[l])+(a[l]<a[r]?-1:1);
}
void Solve(int l,int r,int L,int R) {
    if(l>r)return;
    int Mid=l+r>>1,pos=L,mx=-1;
    for(int i=L;i<=R;i++) 
        if(b[i]<d[Mid]) {
            int t=Get(b[i],d[Mid]);
            if(t>mx)mx=t,pos=i;
        }
    Ans=max(Ans,mx);
    Solve(l,Mid-1,L,pos);Solve(Mid+1,r,pos,R);
}
void Update(int x) {
    for(;x<=n;x+=x&-x) ++s[x];
}
int Query(int x) {
    int Ans=0;
    for(;x;x-=x&-x) Ans+=s[x];
    return Ans;
}
int main() {
    Read(n);
    for(int i=1;i<=n;i++) {
        Read(x);a[i]=x;
        Update(Rt[i],Rt[i-1],1,n,x);
        if(x>a[b[l1]]) b[++l1]=i;
        while(l2&&a[d[l2]]>x) l2--;d[++l2]=i;
    }
    int t=0;
    Solve(1,l2,1,l1);
    for(int i=n;i;i--) sum+=Query(a[i]),Update(a[i]);
    cout<<sum-max(Ans-1,0)<<endl;
    return 0;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值