zoukankan      html  css  js  c++  java
  • codeforces 1042D

    题目:戳这里

    题意:有n个数,问有多少个区间满足[L,R]内的和小于t。

    解题思路:

    [L,R]内的和小于t等价于sum[R]-sum[L-1]<t,将sum[L-1]左移,可以看出R与L的关系sum[R]<sum[L-1]+t。

    因为n个数有正有负,所以前缀和sum[]没法直接二分,需要构造出一个有序的前缀和。这样就可以想到用树状数组来维护前缀和,考虑到树状数组维护前缀和,将R和L的关系改为sum[R]-t<sum[L-1]更好写一些(个人习惯,固定r,二分出l)。然后就转化成了常规的离散化树状数组的题目:遍历R,二分查找l,加入答案,更新树状数组。

    附ac代码:

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef long long ll;
     4 const int inf = 0x3f3f3f3f;
     5 const int maxn = 2e5 + 10;
     6 #define lowbit(x) x&-x
     7 ll sum[maxn];
     8 ll a[maxn];
     9 ll c[maxn];
    10 ll tem[maxn];
    11 ll n, t;
    12 void add(ll x, ll u) {
    13     while(x <= n) {
    14         c[x] += u;
    15         x += lowbit(x);
    16     }
    17 }
    18 ll getsum(ll x) {
    19     ll res = 0;
    20     while(x) {
    21         res += c[x];
    22         x -= lowbit(x);
    23     }
    24     return res;
    25 }
    26 int main() {
    27     ll ans = 0;
    28     scanf("%lld %lld", &n, &t);
    29     for(ll i = 1; i <= n; ++i) {
    30         scanf("%lld", &a[i]);
    31         sum[i] = sum[i - 1] + a[i];
    32         if(sum[i] < t) ++ans;
    33     }
    34     for(ll i = 1; i <= n; ++i) {
    35         tem[i] = sum[i];
    36     }
    37     sort(tem + 1, tem + 1 + n);
    38     for(ll i = 1; i <= n; ++i) {
    39         ll x = lower_bound(tem + 1, tem + 1 + n, sum[i]) - tem;
    40         ll y = upper_bound(tem + 1, tem + 1 + n, sum[i] - t) - tem;
    41         ans += (i - 1 - getsum(y - 1));
    42         add(x, 1ll);
    43     }
    44     printf("%lld
    ", ans);
    45     return 0;
    46 }
    View Code
  • 相关阅读:
    C语言 va_start 宏
    C语言 strcat_s 函数
    C语言 strcat 函数
    C语言 memcpy_s 函数
    C语言 memcpy 函数
    C语言 strcpy_s 函数
    C语言 strcpy 函数
    C语言 sizeof 函数
    c++实现扫雷游戏 初学
    .Net vs .Net Core,我该如何选择?看这一篇文章就够了
  • 原文地址:https://www.cnblogs.com/zmin/p/9917868.html
Copyright © 2011-2022 走看看