zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    使用node调用支付宝生成支付二维码(沙箱环境)
    nodejs+mysql嵌套查询的问题
    移动端H5开发问题记录
    在jquery中,使用ajax上传文件和文本
    css百分比值到底参考谁?
    vue cli3 + cube-ui 配置rem踩坑记录
    MFC【exe】工程中的文件大致信息(翻译的)
    ActiveX、OLE和COM/DCOM
    系统版本
    图形库
  • 原文地址:https://www.cnblogs.com/a249189046/p/9664895.html
Copyright © 2011-2022 走看看