1042.D Petya and Array 前缀 + 树状数组

11.19.2018

1042.D Petya and Array
New Point:

前缀 + 树状数组 :树状数组逐个维护前缀个数

Describe:

给你一个数组,一个标记数,问你有多少区间[l,r]使得这个区间的和小于这个标记数值

Solution:

没能想到

前缀数组 + 树状数组快速查询

记录前缀数组sum[i],得到区间和为sum[i] - sum[j] < t,转化为求sum[i] - t < sum[j],遍历i,求取情况,然后利用树状数组快速查询符合的区间j的个数

树状数组维护的是 sum[j],而且遍历i[1,n]的时候j的范围是[0,i-1],所以对于一个新i,我们应该找到sum[i-1]在树上的位置进行全局更新,但是对于第一个i,更新sum[0] = 0即可,可以想到j取0的时候表示a1 + …… + ai

Code:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
const int maxn = 2e5 + 1e3;
ll sum[maxn];
ll f[maxn];
ll tree[maxn];
int n;
ll lowbit(ll x)
{
    return x & (-x);
}
void add(ll x)
{
    while(x <= n+1)
    {
        ++tree[x];
        x += lowbit(x);
    }
}
ll Get(ll x)
{
    ll ans = 0;
    while(x > 0)
    {
        ans += tree[x];
        x -=lowbit(x);
    }
    return ans;
}
int main()
{
    ll t;
    while(~scanf("%d %lld",&n,&t))
    {
        memset(sum,0,sizeof(sum));
        memset(tree,0,sizeof(tree));
        for(int i = 1;i <= n;++i)
        {
            scanf("%lld",&sum[i]);
            sum[i] += sum[i-1];
            f[i] = sum[i];
        }
        f[0] = 0;
        sort(f,f+n+1);
        ll ans = 0;
        for(int i = 1;i <= n;++i)
        {
            add(lower_bound(f,f+n+1,sum[i-1]) + 1 - f);
            ans += i - Get(lower_bound(f,f+n+1,sum[i] - t + 1) - f);
        }
        printf("%lld\n",ans);
    }
    return 0;
}

原文地址:https://www.cnblogs.com/DF-yimeng/p/9988177.html

时间: 2024-10-17 04:27:55

1042.D Petya and Array 前缀 + 树状数组的相关文章

Codeforces 220B - Little Elephant and Array 离线树状数组

This problem can be solve in simpler O(NsqrtN) solution, but I will describe O(NlogN) one. We will solve this problem in offline. For each x (0?≤?x?<?n) we should keep all the queries that end in x. Iterate that x from 0 to n?-?1. Also we need to kee

codeforces 703D Mishka and Interesting sum 偶数亦或 离线+前缀树状数组

题目传送门 题目大意:给出n个数字,m次区间询问,每一次区间询问都是询问 l 到 r 之间出现次数为偶数的数 的亦或和. 思路:偶数个相同数字亦或得到0,奇数个亦或得到本身,那么如果把一段区间暴力亦或,得到的其实就是出现次数为奇数的数字的亦或和,所以我们希望这段区间内的所有数字出现次数都+1,使奇偶性互换. 我们先处理出前缀的亦或和,这样可以得到次数为奇数的亦或和. 接下来的问题就是要改变一段区间的奇偶性了,也就是说,这个问题其实就转化成了如何求一段区间出现的所有数字(无重复). 这里我学到的是

D. Petya and Array 树状数组

题意: 给出一个数组,元素有正有负有0,问其区间和小于 t 的子区间的个数. sum[ r ]-sum[ l-1 ]<t,其中sum是a的前缀和. 实现的方法就是从前往后对于每一个sum[ i ],看在它前面有多少个大于等于sum[ i ] - t 的前缀和. 树状数组维护的是 i 前面有几个数小于等于它 1 #include <cstdio> 2 #include <cstring> 3 #include <queue> 4 #include <cmath

高级数据结构:优先队列、图、前缀树、分段树以及树状数组详解

优秀的算法往往取决于你采用哪种数据结构,除了常规数据结构,日常更多也会遇到高级的数据结构,实现要比那些常用的数据结构要复杂得多,这些高级的数据结构能够让你在处理一些复杂问题的过程中多拥有一把利器.同时,掌握好它们的性质以及所适用的场合,在分析问题的时候回归本质,很多题目都能迎刃而解了. 这篇文章将重点介绍几种高级的数据结构,它们是:优先队列.图.前缀树.分段树以及树状数组. 一.优先队列 1.优先队列的作用 优先队列最大的作用是能保证每次取出的元素都是队列中优先级别最高的,这个优先级别可以是自定

ACdreamoj 1011(树状数组维护字符串hash前缀和)

题目链接:http://acdream.info/problem? pid=1019 题意:两种操作,第一种将字符串某个位置的字符换为还有一个字符.另外一种查询某个连续子序列是否是回文串: 解法:有两种hash的办法,所以写了两种解法;首先hash是x1 * p^1+ x2*p^2 +x3*p^3...能够用树状数组维护前缀和,维护两个串,一个是正串.还有一个是反串用于比較.比較时候乘以对应的p倍数推断是否相等. 刘汝佳白书上的hash方法处理这道题更复杂:改动i会对后缀j产生的影响为a*p^(

AtCoder Regular Contest 075 E - Meaningful Mean 树状数组求顺序对, 前缀和

题目链接: http://arc075.contest.atcoder.jp/tasks/arc075_c 题意: 给你一个序列和一个数k,求有多少对l,r,使得a[l]+a[l+1]+...+a[r]的算术平均数大于等于k 1≤N≤2×10^5 1≤K≤10^9 1≤ai≤10^9 思路: 首先对于所有数减去k,这样就不用除(r-l+1), 然后我们发现所求的就是有多少对l,r,使得sum[r]-sum[l-1] >= 0, sum是减去k之后的序列的前缀和 用树状数组对sum求有多少个顺序对

hdu 5480|| bestcoder   #57 div 2 Conturbatio(前缀和||树状数组)

Conturbatio Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 211    Accepted Submission(s): 99 Problem Description There are many rook on a chessboard, a rook can attack the row and column it bel

HDU5147 Sequence II(树状数组+前缀和+后缀和)

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5147 题意: 统计有多少个四元组,满足a[i]<a[j]<a[k]<a[q] i<j<k<p 分析: 要统计四元组的数量我们可以通过枚举c,然后统计区间[1,c-1]有多少二元组(a,b)满足a<b且Aa<Ab,以及统计出区间 [c+1,n]有多少d满足Ac<Ad,根据乘法原理,把这两项乘起来就可以统计到答案里了. 然后我们来处理子问题:区间[1,c-1

HDU 3854 Glorious Array(树状数组)

题意:给一些结点,每个结点是黑色或白色,并有一个权值.定义两个结点之间的距离为两个结点之间结点的最小权值当两个结点异色时,否则距离为无穷大.给出两种操作,一种是将某个结点改变颜色,另一个操作是询问当前距离小于K的结点有多少对,K是一个定值. 思路:先求最初时候小于k的结点有多少对,然后每次改变颜色的时候,统计该点左侧和右侧各有多少同色和异色的结点(这一步使用树状数组),分别处理就行.另外需要预处理离某个结点最近的两个距离小于K的结点的位置. 代码写的略乱. #include<cstdio> #