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\n");
        else
        printf("0\n");
        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\n",res);
    return 0;
}

原文地址:https://www.cnblogs.com/a249189046/p/9664895.html

时间: 2024-10-12 20:22:50

Codeforces Round #510 (Div. 2) D. Petya and Array (权值线段树)的相关文章

Codeforces Round #423 (Div. 2) C 思维,并查集 或 线段树 D 树构造,水

Codeforces Round #423 (Div. 2, rated, based on VK Cup Finals) C. String Reconstruction   思维,并查集 或 线段树 题意:一个字符串被删除了,但给出 n条信息,要还原出可能的字典序最小的字符串.信息有:字符串ti,ki个位置xi,表明原本的字符串在xi位置是以字符串ti开头的. tags:惨遭 fst,一开始把所有字符串都存下来,排序做的,结果爆内存了.. 方法1: 考虑并查集,对于字符串 ti,在位置xi,

Codeforces Round #393 (Div. 2) E题Nikita and stack(线段树)解题报告

Nikita has a stack. A stack in this problem is a data structure that supports two operations. Operation push(x) puts an integer x on the top of the stack, and operation pop() deletes the top integer from the stack, i. e. the last added. If the stack

Codeforces Round #343 (Div. 2) D. Babaei and Birthday Cake(线段树+离散化优化DP)

题目链接:点击打开链接 题意:给出n个圆柱体的地面半径和高, 要求只能有一个直接放在桌子上, 其他的要放在他上面, 第i个能放在第j个上面的条件是:当且仅当第i个的体积大于第j个且j < i . 求能叠起来的最大体积. 思路:一看就是一个DP, 而且状态很容易表示, d[i]表示到第i个为止能得到的最大总体积.   转移到 max(d[j]) + a[i], (j < i && a[i] > a[j]).  但是n非常大, 显然要优化, 因为第二层循环所做的事情就是在i之

Codeforces Round #261 (Div. 2) D. Pashmak and Parmida&#39;s problem (树状数组求逆序数 变形)

题目链接 题意: 给出一些数a[n],求(i, j), i<j 的数量,使得:f(1, i, a[i]) > f(j, n, a[j]) . f(lhs, rhs, x) 指在 { [lhs, rhs]范围中,a[k]的值=x } 的数量. 1.  f(1, i, a[i]) 就是指a[i]前面包括a[i]的数中,有几个值=a[i]. 2.  f(j, n, a[j]) 就是指a[j]后面包括a[j]的数中有几个值=a[j]. 虽然a[x]范围不小,但是n的范围是1000,不是很大,所以我们可

Codeforces Round #258 (Div. 2) B. Sort the Array(简单题)

题目链接:http://codeforces.com/contest/451/problem/B ---------------------------------------------------------------------------------------------------------------------------------------------------------- 欢迎光临天资小屋:http://user.qzone.qq.com/593830943/ma

Codeforces Round #261 (Div. 2) D. Pashmak and Parmida&#39;s problem (树状数组)

D. Pashmak and Parmida's problem time limit per test 3 seconds memory limit per test 256 megabytes input standard input output standard output Parmida is a clever girl and she wants to participate in Olympiads this year. Of course she wants her partn

Codeforces Round #425 (Div. 2) B. Petya and Exam(暴力大法好)

题目链接:http://codeforces.com/problemset/problem/832/B 题意:给定一些小写字符(定义为好字符,除这些好字符外的其他小写字符都是坏字符).和字符串S,S里面除了小写字母以外还有?字符,?可以用任何的好字符替代:*字符,*只可以用坏字符串和 空替代,然后给出n个字符串去匹配S字符,问是否能成功. 题解:QAQ,这道题写的我头发又掉了好多. 设拿来匹配S的字符串为T 字符串要匹配,长度要相同吧.*既然这么强大,可以空,那么T的长度最多比S的长度少1:然后

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

第一次CF祭== 由于太菜了只做了前两题== 因为在第一题上耗费时间太多了,我还是太菜了==. A. Benches time limit per test 1 second memory limit per test 256 megabytes There are nn benches in the Berland Central park. It is known that aiai people are currently sitting on the ii-th bench. Anoth

Codeforces Round #510 (Div. 2) B. Vitamins

B. Vitamins 题目链接:https://codeforces.com/contest/1042/problem/B 题意: 给出几种药,没种可能包含一种或多种(最多三种)维生素,现在问要吃到这三种维生素买药最少花费是多少. 题解: 嗯...可以直接暴力: #include <bits/stdc++.h> using namespace std; typedef long long ll; const int N = 2e5+5; int n; int c[N]; char s[N][