zoukankan      html  css  js  c++  java
  • CDQ分治--------寒假作业

    题目大意:

    给定一个长度为n的序列a[]以及k,问a[]中有多少个子序列的平均值不小于k

    n<=1e5; 1<=a[i],k<=1e4

    做题心路历程:

    emm,看到这道题目,我当时有点懵逼(这也是CDQ?!),然后我特别疑惑

    仔细思考,根据套路先将原序列中的每个数减去一个k,求序列k中有多少子序列之和大于0

    然后我也没啥头绪了,就来了个前缀和,想打暴力了,然后静坐五分钟,woc,n^2暴力不是有个这样的式子吗:

    if( sum[i] - sum[j] >=0 )total++;( i > j )

    昂?WTF?!这不是二维偏序吗?一个偏序对(i,sum[i]),如果存在一个偏序对(j,a[j])使得i > j && sum[i] >=sum[j]不就可以答案+1了吗

    哦吼,这道题就没了啊.

    思路:

    1.首先将原序列中的每个数减去一个k

    2.然后求一次前缀和

    3.CDQ分治做一个二维偏序(每次统计答案要统计已经插入了多少序列1的数)*(序列1元素的数组下标小于序列二元素的数组下标)

    #include <bits/stdc++.h>
    using namespace std;
    #define ll long long//这道题一定要开long long,不然是90分
    ll n,k;
    ll a[100005],b[100005],sum[100005],ans=0;
    ll CDQ(ll l,ll r){
        if(l == r)return 0;
        ll mid=(l+r)>>1;
        CDQ(l,mid);CDQ(mid+1,r);//递归处理子问题
        ll t1=l,t2=mid+1;
        for (ll i = l ; i <= r ; i ++){
            if(sum[t1] <= sum[t2] && t1 <= mid|| t2 > r)
            b[i]=sum[t1],t1++;
            else b[i]=sum[t2],t2++,ans+=t1-l;//统计答案,总答案加上已经插入了的序列1的数的个数
        }
        for (ll i = l ; i <= r ; i ++)sum[i]=b[i];
        return 0;
    }
    int main(){
        cin>>n>>k;
        for (ll i = 1 ; i <= n ; i ++)
        cin>>a[i],a[i]-=k;//将原序列减去一个k
        for (ll i = 1 ; i <= n ; i ++)
        sum[i]=sum[i-1]+a[i];//求一遍前缀和
        CDQ(0,n);//来个CDQ求二维偏序
        cout<<ans;
        return 0;
    }
  • 相关阅读:
    深入解析ES6中的promise
    深入解析ES6中的promise
    2019年底前的web前端面试题初级-web标准应付HR大多面试问题
    2019年底前的web前端面试题初级-web标准应付HR大多面试问题
    ES6基础-ES6的扩展
    ES6基础-ES6的扩展
    小程序-优化,部署,细节功能
    小程序-优化,部署,细节功能
    小程序基础-组件
    小程序基础-组件
  • 原文地址:https://www.cnblogs.com/MYCui/p/13535602.html
Copyright © 2011-2022 走看看