2018 计蒜之道 初赛 第三场 小结

题目链接
今天的比赛是下午4点开始的,三点半上完课就匆匆忙忙来了机房准备考试。机房里YPC,ykhrg,廖班和余本翱四位大佬已经等候多时。4点到了,我们便开始分工合作了。我和YPC负责干第二题,看到第二题的数据范围就觉得特别的简单,但是题意描述倒卡了我一会。(以后要增强读题的能力,尤其是CF考试,本来就不是特别强的理解能力加上机翻)第二题实际上就是暴力,于是打了个暴力轻松AC。
#include<algorithm>
#include<cstdlib>
#include<iostream>
#include<cstring>
#include<string>
#include<cstdio>
#define MD 323232323
#define ll long long
using namespace std;
ll read(){
    char c;ll x;while(c=getchar(),c<'0'||c>'9');x=c-'0';
    while(c=getchar(),c>='0'&&c<='9') x=x*10+c-'0';return x;
}
ll n,m,q,k=0,bel[1005];
string s;
struct node{
    ll l,r,y,p,q,vis;
}f[1005];
int main()
{
    n=read();m=read();q=read();
    register int i,j;
    for(i=1;i<=q;i++){
        cin>>s;
        if(s=="I"){
            f[++k]=(node){read(),read(),read(),read(),read()};
            bel[f[k].y]=k;
        }
        if(s=="D"){
            ll x=read();
            f[x].vis=1;bel[f[x].y]=0;
        }
        if(s=="Q"){
            ll ans=0;
            ll x=read(),l=read(),r=read();
            for(j=l;j<=r;j++){
                if(!bel[j]||f[bel[j]].vis) continue;
                if(f[bel[j]].l<=x&&x<=f[bel[j]].r) ans=(f[bel[j]].p*ans%MD+f[bel[j]].q%MD)%MD;
            }
            printf("%lld\n",ans%MD);
        }
    }
    return 0;
}
我打完第二题后,ykhrg和余本翱依旧没能赶下第一题,他们想的都是分数规划的方法,特别的高大上,但是我不会。幸好我不会,才没被带入坑里,最后推出结论A了这题。
于是我就去推结论,我们把给定的p和s看成横纵坐标,则答案要求的就是斜率绝对值最大值,则我们按x轴sort后,发现了一个巧妙的结论:当斜率取最大时,我们所取的两个点必定在sort过的数组里相邻。这个可以给出感性的证明:
以下图为例,如果我们要选最左边的点和最右边的点,那么无论中间的点是在上方还是下方,从中间点连线必定更优。

这里写图片描述

所以只要O(N)扫一遍即可。
#include<bits/stdc++.h>
#define MAXN 100005
using namespace std;
int read(){
    char c;int x=0,y=1;while(c=getchar(),(c<'0'||c>'9')&&c!='-');
    if(c=='-') y=-1;else x=c-'0';while(c=getchar(),c>='0'&&c<='9')
    x=x*10+c-'0';return x*y;
}
int T,n,m,flag;
struct node{
    int a,b;
}F[MAXN];
int cmp(node a,node b){
    return a.a<b.a;
}
double k(int x,int y){
    return (double)abs(F[x].b-F[y].b)/abs(F[x].a-F[y].a);
}
int main()
{
    T=read();
    while(T--){
        double ans=0;
        n=read();flag=0;
        for(int i=1;i<=n;i++) F[i].a=read(),F[i].b=read();
        sort(F+1,F+1+n,cmp);
        for(int i=2;i<=n;i++)
         if(F[i].a==F[i-1].a){puts("-1");flag=1;break;}
        if(flag) continue;
        for(int i=2;i<=n;i++) ans=max(ans,k(i,i-1));
        printf("%.6f\n",ans);
    }
    return 0;
}
第三题虽然可以离线,但蒟蒻表示不会,蒟蒻取请教了ZZK大佬,他在经过大约10分钟的思考后秒了这题,大约是线段树+标记永久化,然而无奈ZZK大佬在打的时候遇到了一些困难,最终也没A掉,十分可惜。

猜你喜欢

转载自blog.csdn.net/stevensonson/article/details/80378332