【NOIP2016提高组复赛】蚯蚓

版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/doyouseeman/article/details/53396063

Description

这里写图片描述

Solution

这题打暴力,用堆来做,理论上是可以拿80分,所以比赛还是打暴力好。
但是,正解又短又机智。
我们假设x1>x2
那么x1肯定会在x2之前就被剪断。
x1被剪成p1q1p1=px1,q1=x1px1
x2被剪成p2q2p2=px2,q2=x2px2
我们可以得到一个很显然的结论,p1>p2q1>q2,也就是说p1一定会在p2之前被剪断,q1一定会在q2之前被剪断。
我们来简单的证明一下:
假设x1剪断之后到剪断x2经过了i的时间,
那么此时x2=x2+iq,p1=px1+iqq1=x1px1+iq
剪断x2之后p2=p(x2+iq),q2=x2+iqp(x2+iq)
我们先比较一下p1p2的大小关系:
我们如果不考虑取整的话,p1p2=p(x1x2)+q(iip),因为p是小于1的,所式子一定是大于0的。
p2q2的大小关系同理。
得证。
那么知道了这个结论之后要怎么去用呢。
我们设三个队列,一个a[0],a[1],a[2]。
a[0]预先存原序列的从大到小的排序。
a[1]存px的从大到小排序
a[2]存x-px的从大到小排序
那么每次取出最大的队首,然后拆掉存到a[1]和a[2]中,根据结论这样一定合法。

Code

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define fo(i,a,b) for(i=a;i<=b;i++)
using namespace std;
const int maxn=7100007;
typedef long long ll;
ll i,j,k,t,n,m,ans,p,q,u,v,da,x,y,tt;
ll a[3][maxn],l[3],r[3];
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,&tt);
    fo(i,1,n+m)a[0][i]=a[1][i]=a[2][i]=-0x7fffffff;
    fo(i,1,n)scanf("%lld",&a[0][i]);
    sort(a[0]+1,a[0]+1+n,cmp);
    l[0]=1,r[0]=n;l[1]=l[2]=1;r[1]=r[2]=0;
    fo(i,1,m){
        da=-0x7fffffff;
        fo(j,0,2){
            if(a[j][l[j]]>da)da=a[j][l[j]],k=j;
        }
        t=da+(i-1)*q;
        l[k]++;
        if(i%tt==0)printf("%lld ",t);
        x=t*u/v;y=t-x;
        a[1][++r[1]]=x-i*q;
        a[2][++r[2]]=y-i*q;
    }
    printf("\n");
    fo(i,1,n+m){
        da=-0x7fffffff;
        fo(j,0,2){
            if(a[j][l[j]]>da)da=a[j][l[j]],k=j;
        }    
        t=da+m*q;
        l[k]++;
        if(i%tt==0)printf("%lld ",t);
    }
}
展开阅读全文

没有更多推荐了,返回首页