Codeforces Round #510 (Div. 2) D. Petya and Array (权值线段树)

Posted a249189046

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforces Round #510 (Div. 2) D. Petya and Array (权值线段树)相关的知识,希望对你有一定的参考价值。

题目地址:http://codeforces.com/contest/1042/problem/D

题意:给你n个数,问有多少个区间的和的值小于t

分析:区间和问题,常常用到前缀和来进行预处理,所以先预处理出前缀和数组sum

           sum[i]代表前i个数的和,那么sum[i]的贡献就是,  当i<k<=n时,存在多少个k,使sum[k]<t+sum[i]

           也就是求在[i+1,n]中,小于t+sum[i]的数有多少。

           所以我们可以类比于询问一个数是区间第几大的方法,使用权值线段树来解决,这里因为数的范围较大,首先需要进行离散化处理。

 

代码如下:

#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <iostream>
#include <vector>
#include <cstring>
#include <map>
using namespace std;
const int N=2e5+100;
typedef long long LL;
vector<LL>V;
int T[N<<3];
LL res;
LL sum[N];
LL a[N];
LL n,t;

int get_id(LL x)  //离散化处理
{
  return lower_bound(V.begin(),V.end(),x)-V.begin()+1;
}

void BuildTree(int rt,int l,int r)
{
  T[rt]=0;
  if(l==r)return;
  int mid=(l+r)>>1;
  BuildTree(rt<<1,l,mid);
  BuildTree(rt<<1|1,mid+1,r);
}

void Updata(int p,int v,int rt,int l,int r)  //插入v个值为p的数,若v为负数,即为删去.
{
  T[rt]+=v;
  if(l==r)return;
  int mid=(l+r)>>1;
  if(p<=mid)Updata(p,v,rt<<1,l,mid);
  else Updata(p,v,rt<<1|1,mid+1,r);
}


void less_num(int pos,int rt,int l,int r)
{
   if(l==r)
   return;
   int mid=(l+r)>>1;
   if(pos<=mid)
   less_num(pos,rt<<1,l,mid);
   else
   {
     res+=T[rt<<1];
     less_num(pos,rt<<1|1,mid+1,r);
   }
}



int main()
{
    scanf("%lld%lld",&n,&t);
    for(int i=1;i<=n;i++)
    {
      scanf("%lld",&a[i]);
      sum[i]=sum[i-1]+a[i];
      V.push_back(sum[i]);
    }
    if(n==1)
    {
        if(a[1]<t)
        printf("1
");
        else
        printf("0
");
        return 0;
    }
    for(int i=1;i<=n;i++)
    {
      LL x=sum[i]+t;
      V.push_back(x);
    }
    sort(V.begin(),V.end());
    V.erase(unique(V.begin(),V.end()),V.end());
    int len=V.size();
    BuildTree(1,1,len);
    Updata(get_id(sum[n]),1,1,1,len);
    for(int i=n-1;i>=0;i--)
    {
       LL x=sum[i]+t;
       less_num(get_id(x),1,1,len);
       if(i>0)
       Updata(get_id(sum[i]),1,1,1,len);
    }
    printf("%lld
",res);
    return 0;
}

 

以上是关于Codeforces Round #510 (Div. 2) D. Petya and Array (权值线段树)的主要内容,如果未能解决你的问题,请参考以下文章

Codeforces Round #510 (Div. 2)(A)

Codeforces Round #510 Div. 2 Virtual Participate记

Codeforces Round #510 (Div. 2) C. Array Product

Codeforces Round #510 (Div. 2) D. Petya and Array(树状数组)

Codeforces Round #510 (Div. 2) A&B By cellur925

Codeforces Round #510 (Div. 2) D. Petya and Array (权值线段树)