Forças de código Rodada # 510 (Div. 2) D. Petya e Array
Petya tem uma matriz a consistindo de n inteiros. Ele aprendeu somas parciais recentemente e agora pode calcular a soma dos elementos em qualquer segmento da matriz com muita rapidez. O segmento é uma sequência não vazia de elementos posicionados um ao lado do outro na matriz.
Agora ele se pergunta qual é o número de segmentos em sua matriz com a soma menor que t. Ajude Petya a calcular este número.
Mais formalmente, você deve calcular o número de pares l, r (l≤r) de modo que al + al + 1 + ⋯ + ar <t a_l + a_ {l + 1} + \ cdots + a_r <tumal+umal + 1+⋯+umar<t .
Entrada
A primeira linha contém dois inteiros n e t (1≤n≤200000, | t | ≤2e14).
A segunda linha contém uma sequência de inteiros a1, a2,…, an (| ai | ≤1e9) - a descrição do array de Petya. Observe que pode haver elementos negativos, zero e positivos.
Resultado
Imprima o número de segmentos na matriz de Petya com a soma dos elementos menor que t.
Exemplos
entrada
5 4
5 -1 3 4 -1
resultado
5
entrada
3 0
-1 2 -3
resultado
4
entrada
4 -1
-2 1 -2 3
resultado
3
O significado da pergunta é muito simples. Descubra quantos intervalos em 1-n cuja soma é menor que ttt , transformamos ligeiramente:
al + al + 1 +… + ar <t a_l + a_ {l + 1} + \ cdots + a_r <tumal+umal + 1+⋯+umar<t
则:
soma [r] - soma [l - 1] <t soma [r] -soma [l-1] <ts u m [ r ]-s u m [ l-1 ]<t
soma [r] - soma [l - 1] ≤ t - 1 soma [r] -sum [l-1] \ leq t-1s u m [ r ]-s u m [ l-1 ]≤t-1
soma [r] ≤ soma [l - 1] + t - 1 soma [r] \ leq soma [l-1] + t-1s u m [ r ]≤s u m [ l-1 ]+t-1 A
soma do prefixo pode ser pré-processada e o título é convertido para um certo númeroxxx , encontre menor ou igual ax + t - 1 x + t-1x+t-O número de elementos de 1 , é fácil pensar na árvore de segmento de linha ponderada para encontrar rapidamente o número menor ou igual a um determinado número no intervalo. Este problema deve ser discretizado devido à quantidade de dados. Use umvetor vetorialv e c t o r armazena todas as somas de prefixo, então o subscrito de cada soma de prefixo é o subscrito na árvore de segmento após eles serem separados, então o título é o prefixo e o número de cada prefixo e consulta que atendem às condições. Preste atenção aovetor vetorialOs elementos em v e c t o r devem ser desduplicados, porque a árvore do segmento de linha ponderada retém o estado da última inserção. Se você não desduplicar, a resposta será repetida. O código AC é o seguinte:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=4e5+5;
int n,m,k;
ll t,a[N],sum[N],tree[N<<2];
vector<ll>v;
int getpos(ll x){
return lower_bound(v.begin(),v.end(),x)-v.begin()+1;
}
void pushup(int i)
{
tree[i]=tree[i<<1]+tree[i<<1|1];
}
void build(int i,int l,int r)
{
if(l==r)
{
tree[i]=0;
return ;
}
int mid=l+r>>1;
build(i<<1,l,mid);
build(i<<1|1,mid+1,r);
pushup(i);
}
void update(int i,int l,int r,int x,int k)
{
if(l==r)
{
tree[i]+=k;
return ;
}
int mid=l+r>>1;
if(x<=mid) update(i<<1,l,mid,x,k);
else update(i<<1|1,mid+1,r,x,k);
pushup(i);
}
ll query(int i,int l,int r,int m,int n)
{
if(m<=l&&r<=n) return tree[i];
int mid=l+r>>1;
ll ans=0;
if(m<=mid) ans+=query(i<<1,l,mid,m,n);
if(n>mid) ans+=query(i<<1|1,mid+1,r,m,n);
return ans;
}
int main(){
scanf("%d%lld",&n,&t);
v.push_back(t-1);
for(int i=1;i<=n;i++){
scanf("%lld",&a[i]);
sum[i]=sum[i-1]+a[i];
v.push_back(sum[i]);
v.push_back(sum[i]+t-1);
}
if(n==1){
if(a[1]<t) printf("1");
else printf("0");
}else{
sort(v.begin(),v.end());
v.erase(unique(v.begin(),v.end()),v.end());
m=v.size();
build(1,1,m);
ll ans=0;
for(int i=n;i>=0;i--){
ans+=query(1,1,m,1,getpos(sum[i]+t-1));
update(1,1,m,getpos(sum[i]),1);
}
printf("%lld\n",ans);
}
return 0;
}