连续非空子序列

先求一遍前缀和数组为h
需要求满足 && 的式子
题目就转为求前缀和数组中逆序对的数目
使用归并排序求逆序对
或使用高级数据结构维护(如平衡树)

参考代码(归并排序)

#include<bits/stdc++.h>
using namespace std;
long long n;
long long h[1000008]; 
long long a[1000008];
long long c[1000008];
long long ans;
void fsort(long long l,long long r)
{
    if(l>=r) return ;
    long long tot=0;
    long long mid=(l+r)/2;
    long long aa=l,bb=mid+1;
    fsort(l,mid);
    fsort(mid+1,r);
    while(aa<=mid&&bb<=r){
        if(a[aa]<a[bb]){
            c[++tot]=a[aa++];
            ans+=(r-bb+1);
        }
        else{
            c[++tot]=a[bb++];
        }
    }
    while(aa<=mid)
        c[++tot]=a[aa++];
    while(bb<=r)
        c[++tot]=a[bb++];
    for(long long i=l,j=1;i<=r;i++,j++)
        a[i]=c[j];
}
int main()
{
    scanf("%lld",&n);
    a[1]=h[1]=0;
    n++;
    for(long long i=2;i<=n;i++){
        scanf("%lld",&h[i]);
        a[i]=a[i-1]+h[i];
    }
    fsort(1,n);
    cout<<ans<<"\n";
    return 0;
}

参考代码(Splay树)

#include<bits/stdc++.h>
#define ll long long
#define int long long
#define inf INT_MAX
#define lc(x) s[x].ch[0]
#define rc(x) s[x].ch[1]
using namespace std;
const int N=1e6+10;
int n,rt,tot;
int a[N];
struct nkl {
    int ch[2],siz,cnt,val,fa;
} s[N];
inline int ident(int x,int y) {
    return (rc(y)==x);
}
inline void cn(int x,int y,int k) {
    s[x].fa=y;
    s[y].ch[k]=x;
}
inline void upd(int x) {
    s[x].siz=s[lc(x)].siz+s[rc(x)].siz+s[lc(x)].cnt+s[rc(x)].cnt;
}
inline void rotate(int x) {
    int y=s[x].fa,z=s[y].fa,k=ident(x,y);
    cn(s[x].ch[k^1],y,k);
    cn(x,z,ident(y,z));
    cn(y,x,k^1);
    upd(y),upd(x);
}
inline void splay(int x,int to) {
    if(!to) rt=x;
    while(s[x].fa!=to) {
        int y=s[x].fa,z=s[y].fa;
        if(z!=to)
            ident(x,y)^ident(y,z) ? rotate(x):rotate(y);
        rotate(x);
    }
}
inline void newcode(int &now,int x,int fa) {
    now=++tot;
    s[now].val=x;
    s[now].fa=fa;
    s[now].cnt++;
}
inline void ins(int &now,int x,int fa) {
    if(!now) newcode(now,x,fa),splay(now,0);
    else if(s[now].val<x) ins(s[now].ch[1],x,now);
    else if(s[now].val>x) ins(s[now].ch[0],x,now);
    else s[now].cnt++,splay(now,0);
}
signed main() {
    scanf("%lld",&n);
    for (int i=1; i<=n; i++)
        scanf("%lld",&a[i]),a[i]+=a[i-1];
    ll ans=0;
    for (int i=1; i<=n; i++) {
        ins(rt,a[i],0);
        ans+=s[lc(rt)].siz+s[lc(rt)].cnt;
        if(a[i]>0) ans++;
    }
    printf("%lld\n",ans);
    return 0;
}
全部评论

相关推荐

头像
不愿透露姓名的神秘牛友
04-02 21:36
点赞 评论 收藏
转发
点赞 收藏 评论
分享
牛客网
牛客企业服务