BZOJ 1136 POI2009 Arc 单调队列

来源:互联网 发布:金蝶kis软件视频教程 编辑:程序博客网 时间:2024/06/05 23:59

题目大意:给定一个长度为n的序列,求一个长度为k的子序列,使字典序最大

第一个数肯定是在[1,n-k+1]之间选最大的那个 如果有多个选最左侧的

第二个数肯定是在[b1,n-k+2]之间选最大的那个 如果有多个选最左侧的

第三个数肯定是在[b2,n-k+3]之间选最大的那个……

我们发现区间左右端点都是单调递增的,因此直接用单调队列搞一下就好了


BZ可以这么过 但是去POI官网一看傻了。。。内存32MB!

连原数组都存不下!

因此我们可以加入一个剪枝:

由于我们最后只会取走k个数,因此单调队列的长度>k时直接弹队尾

这样空间复杂度就变成了O(k)的了


然后写代码的时候发现又傻了。。。读入没给n。。。而我们又不能先读入所有数据去判断n。。。

于是我们维护一下后k个数以及前n-k个数的单调队列 这样内存还是O(k)的

就可以过辣。。。


谁知道我为什么过不去样例却能AC。。。


/*************************************************************************}{*                                                                       *}{*                     XVI Olimpiada Informatyczna                       *}{*                                                                       *}{*   Zadanie: Architekci (ARC)                                           *}{*   Plik:    carclib.c                                                  *}{*   Autor:   Bartosz Gorski                                             *}{*   Opis:    Biblioteka do wczytywania danych wejsciowych i wypisywania *}{*            wyniku                                                     *}{*                                                                       *}{*************************************************************************/#include <stdlib.h>#include <stdio.h>#include <time.h>#define MAGIC_BEGIN -435634223#define MAGIC_END -324556462#define MIN_K 1#define MAX_K 1000000#define MAX_N 15000000#define MIN_A 1#define MAX_A 1000000000#define MIN_TYP 1#define MAX_TYP 3#define MIN_PAR 0#define MAX_PAR 1000000000#define ERROR 0#define CORRECT 1#define unlikely(x) __builtin_expect(!!(x), 0)static int init = 0; // czy zostala juz wywolana funkcja inicjuj()static int lib_n; // ile biblioteka podala juz liczbstatic int con_k; // ile zawodnik podal liczbstatic int N, K, A, TYP, PAR; // parametry testu wczytywane z plikustatic int bre, len_sub, bou, is_end; // zmienne pomocniczestatic int rand2_status = 198402041;static inline int rand2(int a, int b){  rand2_status = rand2_status * 1103515245 + 12345;  int x = rand2_status;  if (x < 0) x = -x; // -2^31 sie nie zdarza :D  x >>= 1;  x = a + x % (b - a + 1);  return x;}/* test losowy */static inline int random_test(){    return rand2(1, A);}/* test z dlugim podciagiem nierosnacym */static inline int decreasing_test(){    int tmp;    if(bre == 0) {        bre = rand2(0, (N - lib_n + 1 - len_sub));        tmp = A;        A -= rand2(0, (A - 1) / len_sub);        len_sub--;    }    else {        bre--;        tmp = rand2(1, A);    }    return tmp;}/* test z dlugim podciagiem niemalejacym */static inline int increasing_test(){    return bou - decreasing_test();}static void finish(int res, char *com){    if(res == ERROR)        printf("%s\n", com);    exit(0);}/* Inicjuje dane wejsciowe i zwraca liczbe projektow */int inicjuj(){    if(init == 1)        finish(ERROR, "Program zawodnika moze wywolac funkcje inicjuj tylko raz!!!");    init = 1;    scanf("%d", &K);    if (K > 0){      TYP = 0;      N = MAX_N + 2;      return K;    }    int magic_begin, magic_end;    scanf("%d%d", &magic_begin, &TYP);    if(magic_begin != MAGIC_BEGIN || TYP < MIN_TYP || TYP > MAX_TYP)        finish(ERROR, "Program zawodnika nie moze korzystac z stdin!!!");    scanf("%d%d%d%d", &N, &K, &A, &PAR);    if(N < 1 || N > MAX_N || N < K || K > MAX_K || A < MIN_A || A > MAX_A         || PAR < MIN_PAR || PAR > MAX_PAR)        finish(ERROR, "Program zawodnika nie moze korzystac z stdin!!!");    scanf("%d", &magic_end);    if(magic_end != MAGIC_END)        finish(ERROR, "Program zawodnika nie moze korzystac z stdin!!!");    con_k = 0;    lib_n = 0;    is_end = 0;    if(TYP == 2 || TYP == 3) {        len_sub = PAR;        bre = 0;    }    if(TYP == 2)        bou = A--;    return K;}/* Sluzy do wczytania ciagu reprezentujacego jakosci projektow */int wczytaj(){    if(unlikely(init == 0))        finish(ERROR, "Program zawodnika nie wywolal funkcji inicjuj!!!");    if(unlikely(lib_n > N || is_end == 1))        finish(ERROR, "Program zawodnika wywolal funkcje wczytaj po otrzymaniu informacji o koncu ciagu!!!");    if(unlikely(lib_n == N))        return 0;    lib_n++;    switch (TYP) {      case 0:        scanf("%d", &A);        if(A == 0)          is_end = 1;        return A;        break;      case 1: return random_test(); break;      case 2: return increasing_test(); break;      case 3: return decreasing_test(); break;      default:              finish(ERROR, "Nieznany typ testu");    }    return -1;}/* Sluzy do wypisania wyznaczonego podciagu */void wypisz(int jakoscProjektu){    if(init == 0)        finish(ERROR, "Program zawodnika nie wywolal funkcji inicjuj!!!");    printf("%d\n", jakoscProjektu);    if(++con_k == K)        finish(CORRECT, "");}#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#define M 1048576using namespace std;int k,n,a[M];struct Monotonous_Queue{int q[M],r,h;void Push(int x){while( (r-h&M-1)>=1 && q[r]<x )(--r)&=M-1;if( (r-h&M-1)<k )q[(++r)&=M-1]=x;}void Pop(){q[(++h)&=M-1]=0;}int Front(){return q[h+1&M-1];}}queue;int main(){int i,x;k=inicjuj();for(i=1;i<=k;i++)a[i]=wczytaj();n=k;while(x=wczytaj(),x){a[(++n)&=M-1]=x;queue.Push(a[n-k&M-1]);}for(i=k-1;~i;i--){queue.Push(a[n-i&M-1]);wypisz(queue.Front());queue.Pop();}return 0;}

0 0
原创粉丝点击