清北学堂国庆day4解题报告

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了清北学堂国庆day4解题报告相关的知识,希望对你有一定的参考价值。

Day4解题报告

张炳琪

时间安排::

T1:30分钟写了个分块暴力 

T2:一个半小时写了个枚举暴力

T3:一个小时写了个搜索暴力

答题情况和错误分析::

T1 100

由于数据是随机的,其实n方暴力就可以,不需要用分块也能过

T260

考场上写了个n^3 * log10000的算法,过了60分,正解挺难想的,也不会写

T310

有点想当然了,将距离理解成了二次函数求极值,没打部分分(而且求极值的方法我不会,用搜索写的)

Tot::170

 

题目解析:

T1

对于每个位置,在左右两方分别找距离它最近的比他大的值,这个可以用单调栈On维护,线段树加二分Onlog2n维护,分块On根号n维护,暴力N^2维护都能过

T2

最终复杂度只能是n^2log级别的,可以先二分边长,之后枚举最上方的行,算出最下方的行,之后将所有点扫一遍,上下界在这个区间的点进行纵坐标排序,n扫一遍判断符合要求的最小值更新答案。

T3:这个题目是计算几何,真的没看出来,可以做出s/t图像 将会发现在每个线段交点处可能存在上下扩展的情况可能成为最小值,近一步讨论可以发现只有在上下凸壳上的交点才有可能在向上向下的扩展中求最大值,所以求凸壳,可以在排序后Nlogn求出,之后枚举点进行计算就能过。不过我觉得我那个推论应该没问题,只是应该把求最值的算法改成三分而不是二分

代码:

T1:

 

#include<cstdio>
#include<algorithm>
#include<cmath>
#include<iostream>
#define MAXN 52521
using namespace std;

int hi[MAXN];
int ver[MAXN];
int kuai[MAXN];
int belong[MAXN];
int get_[MAXN];
int n;
int kuaishu,biaozhun;

int read()
{
    int nm_ = 0;
    char c = getchar();
    while(c > 9 || c < 0)c = getchar();
    while(c >= 0 && c <= 9)
    {
        nm_ *= 10;
        nm_ += c - 0;
        c = getchar();
    }
    return nm_;
}

int find(int be,int ed,int k)
{
    if(be > ed)return 0;
    
    for(int i = ed; i >= (belong[ed] - 1) * biaozhun + 1;i--)
        if(hi[i] > k)
            return i;
    for(int i = belong[ed] - 1;i >= 1;i--)
    {
        if(kuai[i] > k)
        {
            for(int j = i * biaozhun;j >= (i - 1) * biaozhun + 1;j--)
                if(hi[j] > k)
                    return j;
        }
    }
    return 0;
}

int rfind(int be,int ed,int k)
{
    if(be > ed)return 0;
    for(int i = be;i <= min(belong[be] * biaozhun,n);i++)
        if(hi[i] > k)
            return i;
    for(int i = belong[be] + 1;i <= belong[ed];i++)
    {
        if(kuai[i] > k)
            for(int j = (i - 1) * biaozhun + 1;j <= min(n,i * biaozhun);j++)
                if(hi[j] > k)
                    return j;
    }
    return 0;
}

int main()
{
    freopen("treasure.in","r",stdin);freopen("treasure.out","w",stdout);
    n = read();
    biaozhun = sqrt(n);
    for(int i = 1;i <= n;i++)
    {
        belong[i] = ((i - 1) / biaozhun) + 1;
        hi[i] = read();
        ver[i] = read();
        kuai[belong[i]] = max(kuai[belong[i]],hi[i]);
    }
    
    for(int i = 1;i <= n;i++)
    {
        int q = find(1,i - 1,hi[i]);get_[q] += ver[i];
        q = rfind(i + 1,n,hi[i]);get_[q] += ver[i];
    }
    int ans = 0;
    for(int i = 1;i <= n;i++)
    {
        ans = max(ans,get_[i]);
    }
    cout << ans;
    fclose(stdin);fclose(stdout);
    return 0;
 }

 

T2:

#include<cstdio>
#include<algorithm>
#include<iostream>
#define MAXN 2001
using namespace std;
struct Note{
    int x;
    int y;
}note[MAXN]; 
int stack_[MAXN];
int top; 
int p,n;
int ans = 0x7ffffff;

int read()
{
    int nm = 0;
    char c = getchar();
    while(c > 9|| c < 0)c = getchar();
    while(c >= 0 && c <= 9)
    {
        nm *= 10;
        nm += c - 0;
        c = getchar();
    }
    return nm; 
}

bool cmp(Note a, Note b)
{
    return a.x < b.x;
}


bool cango(int be,int ed,int k)
{
    top = 0;
    for(int i = 1;i <= n;i++)
    {
        if(note[i].x >= be && note[i].x <= ed)
            stack_[++top] = note[i].y;
    }
    sort(stack_ + 1,stack_ + top + 1);
    if(top < p)return false; 
    for(int i = p;i <= top;i++)
    {
        ans = min(ans,max(k,stack_[i] - stack_[i - p + 1] + 1));
        if(stack_[i] - stack_[i - p + 1] <= k)return true; 
    }
    return false;
}

bool check_(int k)
{
    for(int i = 1;i <= n;i++)
    {
        int be = note[i].x;
        int ed = be + k - 1;
        if(be > 10000)return false;
        if(cango(be,ed,k))return true;
    }
    return false;
} 

int main()
{
    freopen("square.in","r",stdin);freopen("square.out","w",stdout);
    p = read();n = read();
    for(int i = 1;i <= n;i ++)
    {
        note[i].x = read();
        note[i].y = read();
    }
    sort(note + 1,note + n + 1,cmp);
    
    int l = 1,r = 10000;
    while(l + 1 < r)
    {
        int mid = (l + r) >> 1;
        if(check_(mid))r = mid;
        else l = mid; 
    }
    check_(l);check_(r);
    cout <<ans; 
    return 0;
}

T3:

/*(60分)*/
#include<cstdio>
#include<iostream>
#define MAXN 123456 
using namespace std;
double v[MAXN];
double t[MAXN];
double s[MAXN]; 
int n;

double min(double a,double b)
{
    return a < b ? a : b;
}
double max(double a,double b)
{
    return a > b ? a : b;
}

double check_(double tm)
{
    double minn = 2099999999.0;
    double maxx = 0;
    for(int i = 1;i <= n;i++)
    {
        double op = s[i] + v[i] * tm;// s = vt
        minn = min(minn,op);
        maxx = max(maxx,op); 
    }
    return maxx - minn;
}


int main()
{
    freopen("chase.in","r",stdin);freopen("chase.out","w",stdout);
    scanf("%d",&n);
    double T = 0;
    for(int i = 1;i <= n;i++)
    {
        scanf("%lf%lf",&t[i],&v[i]);
        T = max(T,t[i]);
    }
    for(int i = 1;i <= n;i++)
    {
        s[i] = (T - t[i]) * v[i];//计时开始的时候已经跑过的路程 
    }
    double l = 1,r = 987654321;
    while(r - l > 0.00001)
    {
        double zz = (r - l) / 3.0;
        double ln = l + zz;
        double rn = r - zz;
        double lnow = check_(ln);
        double rnow = check_(rn);
        if(lnow > rnow)l = ln;
        else r = rn;    
    }
    printf("%.2lf",check_(l));
    fclose(stdin);fclose(stdout);
    return 0;
}

 

以上是关于清北学堂国庆day4解题报告的主要内容,如果未能解决你的问题,请参考以下文章

清北学堂国庆day1解题报告

清北学堂国庆day6解题报告

清北学堂国庆day7解题报告

清北学堂国庆day5解题报告

清北学堂国庆day3解题报告

2017.7.21夏令营清北学堂解题报告