• Petya and Array CodeForces


    很不错的一道题

    给你一个长度为n的数组,问共有多少个区间满足区间之和小于给定的数t

    这种题一般做法肯定是枚举,固定左端点枚举右端点,枚举的过程需要优化,否则就是n方

    这道题我先求一个前缀和,然后逆着枚举,显然问题转化为了对于一个数,如果寻找他右边的数哪些小于它+t,这就转化为了区间求和,可以树状数组或者线段树,但是数的范围太大,因此需要用离散化

    这道题的还有一个问题是定位,有一个很简单的定位方法就是把每一个前缀和+t也放进去,这样去定位就很简单了

    另外就是使用upper_bound不过找的数要减一

    具体做法看代码

    #include<bits/stdc++.h>
    using namespace std;
    #define endl "
    "
    #define pf printf
    #define int long long
    #define IO ios::sync_with_stdio(0);cin.tie(0);cout.tie(0)
    const int maxn=200000+5;
    int sum[maxn],a[maxn],up;
    vector<int> v;
    int n,t;
    inline int lowbit(int x){return x&-x;}
    void add(int x,int d)
    {
        while(x<=up){
            sum[x]+=d;x+=lowbit(x);
        }
    }
    int Sum(int x)
    {
        int ret=0;
        while(x>0){
            ret+=sum[x];
            x-=lowbit(x);
        }
        return ret;
    }
    main()
    {
        IO;
        int ans=0;
        cin>>n>>t;
        for(int i=1;i<=n;i++){
            cin>>a[i];
            a[i]+=a[i-1];
            v.push_back(a[i]);
            if(a[i]<t) ans++;
        }
        sort(v.begin(),v.end());
        v.erase(unique(v.begin(),v.end()),v.end());
        up=v.size();
        for(int i=n;i;i--){
            ans+=Sum(upper_bound(v.begin(),v.end(),a[i]+t-1)-v.begin());
            add(lower_bound(v.begin(),v.end(),a[i])-v.begin()+1,1);
        }
        cout<<ans<<endl;
    }
  • 相关阅读:
    JavaScript-----7.循环
    3. CSS新特性之动画
    JavaScript-----6.流程控制:分支
    JavaScript-----5.运算符
    JavaScript-----4.数据类型
    2. CSS新特性之2D转换transform
    JavaScript-----3.变量
    JavaScript-----2初识
    JavaScript---1.计算机的编程基础
    品优购学习心得
  • 原文地址:https://www.cnblogs.com/033000-/p/10373867.html
Copyright © 2020-2023  润新知