zoukankan      html  css  js  c++  java
  • 【NOIP2011提高组T5】聪明的质监员-二分答案+前缀和

    测试地址:聪明的质监员

    做法:可以发现,Y的值是随着W的递增而递减的,满足单调性,因此可以用二分答案把查找答案的复杂度降为O(log n)。设lf为左边界,rt为右边界,lf初始化为0,rt初始化为最大的w[i]+1(即矿石中一个都不满足w[i]≥W的情况),然后进行二分答案。设mid=(lf+rt)/2,对于每个mid,算出Y的值,如果Y<S,则表示左半区间内的数更靠近S,否则表示右半区间内的数更靠近S(想一想,为什么?),一次次地缩小查找范围,就可以找到最好的W了。

    那么现在我们只需解决求Y值的问题,由于区间有m个,如果求每个区间的Yi时都要O(n)的复杂度的话,那么整个求Y值的过程的复杂度就是O(nm),显然是不可能承受的。再分析Yi的特征,发现其由两部分组成:w[i]≥W的矿石数量和它们的价值之和。这两个部分都是一个求和的关系,又考虑到在W相同的情况下,这个区间内数的值是不会变化的,所以我们用两个数组sum1和sum2分别表示区间[1,i]内的w[i]≥W的矿石数量和它们的价值之和,那么如果我们要求一个区间[l,r]的Yi,则:

    Yi=(sum1[r]-sum1[l-1])*(sum2[r]-sum2[l-1])

    这样一来,求Yi的复杂度就降为O(1)了,而sum1和sum2只需计算一次,复杂度为O(n),因而整个求Y值的过程的时间复杂度就是O(n+m),在加上二分答案,整个程序的复杂度就是O((n+m)log n),问题完美解决。

    以下是本人代码:

    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    #define ll long long
    using namespace std;
    ll n,m,S,w[200010],v[200010],lf=0,rt=0,ans;
    ll sum1[200010]={0},sum2[200010]={0};
    int l[200010],r[200010];
    
    ll ab(ll a)
    {
      if (a<0) return -a;
      else return a;
    }
    
    bool calc(ll W)
    {
      sum1[0]=sum2[0]=0;
      for(int i=1;i<=n;i++)
      {
        sum1[i]=sum1[i-1];sum2[i]=sum2[i-1];
        if (w[i]>=W) sum1[i]++,sum2[i]+=v[i];
      }
      ll s=0;
      for(int i=1;i<=m;i++)
        s+=(sum1[r[i]]-sum1[l[i]-1])*(sum2[r[i]]-sum2[l[i]-1]);
      if (ab(s-S)<ans) ans=ab(s-S);
      return s<S;
    }
    
    int main()
    {
      scanf("%lld%lld%lld",&n,&m,&S);
      for(int i=1;i<=n;i++)
      {
        scanf("%lld%lld",&w[i],&v[i]);
    	rt=max(rt,w[i]);
      }
      rt++;
      for(int i=1;i<=m;i++)
        scanf("%d%d",&l[i],&r[i]);
      
      ans=1000000;
      ans=ans*ans;
      
      while(lf<=rt)
      {
        ll mid=(lf+rt)>>1;
    	if (calc(mid)) rt=mid-1;
    	else lf=mid+1;
      }
      
      printf("%lld",ans);
      
      return 0;
    }
    


  • 相关阅读:
    771. Jewels and Stones
    706. Design HashMap
    811. Subdomain Visit Count
    733. Flood Fill
    117. Populating Next Right Pointers in Each Node II
    250. Count Univalue Subtrees
    94. Binary Tree Inorder Traversal
    116. Populating Next Right Pointers in Each Node
    285. Inorder Successor in BST
    292. Nim Game Java Solutin
  • 原文地址:https://www.cnblogs.com/Maxwei-wzj/p/9793882.html
Copyright © 2011-2022 走看看