1. 程式人生 > >【CF1042D】Petya and Array

【CF1042D】Petya and Array

lin 優化 題目 ++ namespace oid hup name include

題目大意:給定一個 N 個數組成的序列,給定一個 T,求有多少個區間滿足\(\sum_{i=l}^ra[i]<T\)

題解:區間和問題可以用前綴和優化,即:求有多少個區間滿足\(sum[r]-sum[l-1]<T\) 成立。移項得:\(sum[l-1]>sum[r]-T\),即:維護 sum 數組中的每個數,前面有多少數滿足以上關系式。直接用平衡樹維護即可。

代碼如下

#include <bits/stdc++.h>
using namespace std;
const int maxn=2e5+10;

struct node{
    #define ls(x) t[x].lc
    #define rs(x) t[x].rc
    int lc,rc,rd,size,cnt;
    long long val;
}t[maxn];
int tot,root;
inline void pushup(int p){
    t[p].size=t[ls(p)].size+t[rs(p)].size+t[p].cnt;
}
inline int newnode(long long val){
    ++tot,t[tot].val=val,t[tot].rd=rand(),t[tot].cnt=t[tot].size=1;
    return tot;
}
inline void zig(int &p){
    int lson=ls(p);
    ls(p)=rs(lson),rs(lson)=p,p=lson;
    pushup(rs(p)),pushup(p);
}
inline void zag(int &p){
    int rson=rs(p);
    rs(p)=ls(rson),ls(rson)=p,p=rson;
    pushup(ls(p)),pushup(p);
}
void insert(int &p,long long val){
    if(!p)p=newnode(val);
    else if(t[p].val==val)++t[p].size,++t[p].cnt;
    else if(val<t[p].val){
        ++t[p].size,insert(ls(p),val);
        if(t[ls(p)].rd>t[p].rd)zig(p);
    }else{
        ++t[p].size,insert(rs(p),val);
        if(t[rs(p)].rd>t[p].rd)zag(p);
    }
}
int query(int p,long long val){
    if(!p)return 0;
    else if(t[p].val>val)return t[p].cnt+t[rs(p)].size+query(ls(p),val);
    else return query(rs(p),val);
}

int n;
long long m,ans,sum[maxn];

void read_and_parse(){
    scanf("%d%lld",&n,&m);
    for(int i=1;i<=n;i++)scanf("%lld",&sum[i]),sum[i]+=sum[i-1];
}

void solve(){
    insert(root,0);
    for(int i=1;i<=n;i++){
        ans+=query(root,sum[i]-m);
        insert(root,sum[i]);
    }
    printf("%lld\n",ans);
}

int main(){
    read_and_parse();
    solve();
    return 0;
}

【CF1042D】Petya and Array