[NOIP2016] 지렁이 (단순성 성행위)

이름

링크

생각

간단한 아이디어는 각각의 모든 지렁이 플러스와 마찬가지로 (다시 힙으로 두 부분으로 잘라 그 최대 복용, 직접 긍정을 유지하기 위해 힙을 사용하는 것입니다 \ (q를 \) ,이 지렁이 마이너스의 새로운 세대로 볼 수있다 \ (시간 * Q \) , 그리고 마지막으로 다시에 플러스, \ (시간 \) 즉, 몇 초)하지만,이 방법은 이루어집니다 \ (O (N + m) 로그 (N + m) \) , 이상 할 수 없습니다

분석은 단순 찾을 수 후, 즉 두 부분을 각각 단조 감소 배열로 절단하는 경우

증명은 매우 간단, 지렁이 길이의 첫 번째 컷하자 \ (LEN1의 \) 절단에서 절단 한 후, \을 (LEN1 \) 이 시간 길이 \ (LEN2 \) , 다음이 \ (LEN2 \) \ (\ LEQ \) \ (LEN1 \) , 즉 그들은 양을 증가 동일한 경우 성장 시간 만 절단 길이하고있다 \ (LEN2 + C \) \ (\ 당량 \) \ (LEN1 + C \) 일정 설정

그러므로 세 개의 어레이 (큐)로 나누어, 각각 첫번째, 두번째 (칼로 절단 후의) 초기 증착 지렁이는 초기 순서는 내림차순 지렁이는 제 배열 후에 잘라낼 수 있도록 두 어레이는 내림차순을 충족 할 수 있도록 뒤에 큐로 지렁이 즉, 지렁이 세 HOL 큐에서 최대 값의 최대 값을 고려

두 번째 질문의 경우, 세 개의 큐는 일종의 병합

시간 복잡도는 () O (nlogn + m의 \ \)

#include<bits/stdc++.h>
#define N 100005
#define M 7000005
using namespace std;
int n,m,q,u,v,t;
int a[3][M],top[3];
int b[N+M],c[N+M];

template <class T>
void read(T &x)
{
    char c;int sign=1;
    while((c=getchar())>'9'||c<'0') if(c=='-') sign=-1; x=c-48;
    while((c=getchar())>='0'&&c<='9') x=x*10+c-48; x*=sign;
}
bool cmp(int a,int b) {return a>b;} 
int main()
{
    read(n);read(m);read(q);
    read(u);read(v);read(t);
    for(register int i=1;i<=n;++i) read(a[0][i]);
    a[0][0]=n;
    top[0]=top[1]=top[2]=1;
    sort(a[0]+1,a[0]+n+1,cmp);
    for(register int i=1;i<=m;++i)
    {
        int maxx=(top[0]>n);
        if(a[maxx][top[maxx]]<a[1][top[1]]&&top[1]<=a[1][0]) maxx=1;
        if(a[maxx][top[maxx]]<a[2][top[2]]&&top[2]<=a[2][0]) maxx=2;
        int len=a[maxx][top[maxx]++]+(i-1)*q;
        int L=(long long)u*len/v;
        int R=len-L;
        a[1][++a[1][0]]=L-q*i;
        a[2][++a[2][0]]=R-q*i;
        if(i%t==0) printf("%d ",len);
    }
    printf("\n");
    int l=top[0],r=top[1];
    while(l<=a[0][0]&&r<=a[1][0])
    {
        if(a[0][l]>a[1][r]) b[++b[0]]=a[0][l++];
        else b[++b[0]]=a[1][r++];
    }
    while(l<=a[0][0]) b[++b[0]]=a[0][l++];
    while(r<=a[1][0]) b[++b[0]]=a[1][r++];
    l=1;r=top[2];
    while(l<=b[0]&&r<=a[2][0])
    {
        if(b[l]>a[2][r]) c[++c[0]]=b[l++];
        else c[++c[0]]=a[2][r++];
    }
    while(l<=b[0]) c[++c[0]]=b[l++];
    while(r<=a[2][0]) c[++c[0]]=a[2][r++];
    for(int i=t;i<=n+m;i+=t) printf("%d ",c[i]+m*q);
    printf("\n");
    return 0;
}

추천

출처www.cnblogs.com/Chtholly/p/11347779.html