【jzoj4907】【NOIP2016提高组】【蚯蚓】【单调队列】

题目大意

【jzoj4907】【NOIP2016提高组】【蚯蚓】【单调队列】_第1张图片

解题思路

可以发现先分裂的不会比后分裂的短,应为本来就比后来的长,一样会长长同样的q,所以没有影响。这样我们就可以开三个队列,分别存原来的数,拆出来的两个数,这样就可以轻松排序。还有可以记录分裂出来的时间,就可以在分裂的时候求出真实的长度。

code

#include
#include
#include
#include
#include
#define LD double
#define LL long long
#define max(x,y) ((x>y)?x:y)
#define min(x,y) ((x
#define fo(i,j,k) for(int i=j;i<=k;i++)
#define fd(i,j,k) for(int i=j;i>=k;i--)
using namespace std;
int const maxn=1e5,maxm=7*1e6,inf=1e9;
int n,m,q,u,v,t,a[4][maxm+10],b[4][maxm+10],p[10][10];
bool cmp(int x,int y){
    return x>y;
}
int main(){
    freopen("earthworm.in","r",stdin);
    freopen("earthworm.out","w",stdout);
    scanf("%d%d%d%d%d%d",&n,&m,&q,&u,&v,&t);
    fo(i,1,n)scanf("%d",&a[1][i]);
    sort(a[1]+1,a[1]+n+1,cmp);p[1][0]=p[2][0]=p[3][0]=1;p[1][1]=n;
    fo(i,1,m){
        int mx=-inf,pi;
        fo(j,1,3)
            if((p[j][0]<=p[j][1])&&(a[j][p[j][0]]+q*(i-b[j][p[j][0]]-1)>mx)){
                mx=a[j][p[j][0]]+q*(i-b[j][p[j][0]]-1);
                pi=j;
            }
        if(i%t==0)printf("%d ",mx);
        p[pi][0]++;
        a[2][++p[2][1]]=1ll*mx*u/v;
        b[2][p[2][1]]=i;
        a[3][++p[3][1]]=mx-1ll*mx*u/v;
        b[3][p[3][1]]=i;
    }
    printf("\n");
    fo(i,1,n+m){
        int mx=-inf,pi;
        fo(j,1,3)
            if((p[j][0]<=p[j][1])&&(a[j][p[j][0]]+q*(m-b[j][p[j][0]])>mx)){
                mx=a[j][p[j][0]]+q*(m-b[j][p[j][0]]);
                pi=j;
            }
        if(i%t==0)printf("%d ",mx);
        p[pi][0]++;
    }
    return 0;
}

你可能感兴趣的:(jzoj,数据结构)