bzoj1136: [POI2009]Arc

传送门
首先我们可以证明1一个区间是合法的当且仅当平均数大于k
于是我们先将所有数减去k,再做前缀和
发现问题转化成了在他前面比他小的最大数。
这个随便单调队列水水九可以了。
话说前面那一大坨东西是什么鬼?

#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 liczb  
static int con_k; // ile zawodnik podal liczb  

static int N, K, A, TYP, PAR; // parametry testu wczytywane z pliku  
static int bre, len_sub, bou, is_end; // zmienne pomocnicze  

static 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, "");  
}//只要Ctrl+C Ctrl+V一下九可以了。
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#define N 1048575
using namespace std;
int n,k,x,h,t,a[N+10],q[N+10];
void push(int x){
    while (((t-h)&N)>=1&&q[t]<x) t=(t-1)&N;
    if (((t-h)&N)<k) t=(t+1)&N,q[t]=x;
}
int main(){
    k=inicjuj();
    for (int i=1;i<=k;i++)
        a[i]=wczytaj();
    n=k;
    while (x=wczytaj(),x){
        n=(n+1)&N; a[n]=x;
        push(a[(n-k)&N]);
    }
    for (int i=k-1;i>=0;i--){
        push(a[(n-i)&N]);
        wypisz(q[(h+1)&N]);
        h=(h+1)&N; q[h]=0;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值