interesting sequence 二分???

算法:

此题一眼看去就像是二分题,其实并不满足二分性质。

假设S为29,从1开始枚举长度为2时,就不满足了,但是最长其实为3.。 1 2 20 10 10 3

正确的算法是用L【i]记录 i 能最多往左扩张长度,R【i】记录i能最多往右扩张的长度。。

/*
 * HONI, zadatak DVONIZ
 * Autor: Goran Zuzic
 *
 * Sluzbeno rjesenje, trebalo bi dobiti sve bodove. Ukupna slozenost O(n lg n).
 *
 */

#include <algorithm>
#include <functional>

#include <ctime>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>

#include <set>
#include <vector>
#include <string>

using namespace std;

const int MAXN = 100100;

int n, S;
int A[MAXN];

int L[MAXN], R[MAXN];
vector<int> Ubaci[MAXN];

int main( void )
{
  while( scanf("%d %d", &n, &S) != EOF )
  {

  for (int i = 0; i < n; ++i) {
    scanf("%d", A + i);
  }

  int a = 0, b = 0;
  int suma = 0;
  while(a < n) {
    if (b < n && suma+A[b] <= S) {
      suma += A[b++];
    } else {
      R[a] = b-a;
      suma -= A[a++];
    }
  }
  printf("sum = %d\n",suma);  
  a = b = n-1;
  while (a >= 0) {
    if (b >= 0 && suma+A[b] <= S) {
      suma += A[b--];
    } else {
      L[a] = a-b;
      suma -= A[a--];
    }
  }

  for (int i = 0; i+1 < n; ++i) {
    int val = min(L[i], R[i+1]);
    printf("%d %d %d\n",val,i - val + 1, i);
    Ubaci[i-val+1].push_back(i); //扩张的起点位置, 到K 
  }

  multiset<int> PQ;
  for (int i = 0; i < n; ++i) {
    while (!PQ.empty() && *PQ.begin() < i)
      PQ.erase(PQ.begin());

    for (vector<int>::iterator it = Ubaci[i].begin(); it != Ubaci[i].end(); ++it) {
      PQ.insert(*it);
      printf("i = %d %d\n", i, *it);
    }
    Ubaci[i].clear();

    if (!PQ.empty())
      printf("%d max = %d\n", (*PQ.rbegin() - i + 1) * 2 , *PQ.rbegin());
    else
      printf("0\n");
  }
}
  return (0-0);
}

 

posted on 2012-10-07 22:51  more think, more gains  阅读(211)  评论(0编辑  收藏  举报

导航