POI2010 Blocks

POI2010 Blocks
N 개의 정수 a [1. N] 를 제시 하고 정수 k 를 제시 합 니 다. 이 제 는 다음 과 같은 작업 을 할 수 있 습 니 다. k 이상 의 정수 a [i] 를 선택 할 때마다 a [i] 를 1 로 줄 이 고 a [i - 1] 또는 a [i + 1] 중 하 나 를 추가 합 니 다.일정한 횟수 의 조작 을 거 친 후에 최대 얼마나 긴 연속 서브 시퀀스 를 선택 할 수 있 는 지 물 어보 면 이 서브 시퀀스 의 모든 수 는 k 보다 작 지 않 습 니 다.
총 M 번 의 질문 을 드 립 니 다. 매번 질문 할 때마다 K 가 다 르 기 때문에 각각 대답 해 야 합 니 다.
입력
첫 줄 의 두 개의 정수 N (N < = 1000000) 과 M (M < = 50).
두 번 째 줄 의 N 개 정 수 는 a [i] (a [i] < = 10 ^ 9) 를 나타 낸다.
세 번 째 줄 M 개의 정수, 세 번 째 정 수 는 i 번 째 문의 k (k < = 10 ^ 9) 를 나타 낸다.
출력
모두 한 줄 로 M 개의 정 수 를 출력 하고 i 번 째 수 는 i 번 째 질문 의 답 을 표시 합 니 다.
nlogn 은 그래도 생각 했 습 니 다. 각각 kd 에서 얻 은 접두사 와. 그리고 단조 로 운 스 택 으로 유지 하고 2 분 마다 그 접두사 와 같은 접 두 사 를 찾 습 니 다.
O (n) 의 방법 도 차이 가 많 지 않 습 니 다. 단조 로 운 스 택 (단조 로 운 감소) 을 유지 한 다음 에 모든 접두사 와 스 택 꼭대기 요소 가 현재 접두사 와 같 을 때 계속 팝 업 됩 니 다. 그러면 가장 좋 은 결 과 를 얻 을 수 있 습 니 다. (정확성 은 생각 합 니 다)
#include 
#include 
#include 
#include 
#include 
using namespace std;
const int M=1000005;

int n,m;
int num[M];
long long sum[M];
int stk[M];

void solve() {
    memset(sum,0,sizeof(sum));
    int tot=0;

    int k;
    scanf("%d",&k);

    stk[tot++]=0;
    for (int i=1;i<=n;++i) {
        sum[i]=sum[i-1]+num[i]-k;
        if (sum[i]1]]) stk[tot++]=i;
    }

    int ans=0;
    for (int i=n;i>=1;--i) {
        while (tot&&sum[i]>=sum[stk[tot-1]]) tot--;
        ans=max(ans,i-stk[tot]);
    }

    printf("%d",ans);
}
int main() {
    cin>>n>>m;
    for (int i=1;i<=n;++i) scanf("%d",&num[i]);
    for (int i=1;i<=m;++i) {
        if (i!=1) printf(" ");
        solve();
    }
    return 0;
}

좋은 웹페이지 즐겨찾기