清北学堂2019.7.13

Day 1 (林永迪)

超级大模拟:

1. 读题能力

2. 代码能力

High Level(先想清楚思路再开始编代码)——一种思考方式

 

 

模拟的例子:

 

 

对于high level的模式:

手里有n张牌,有k个规则,每次规则可以打出一定的牌,请问要打出最少多少次牌(显然运用深搜的知识)

void dfs(剩下多少张牌没打last,打了多少次牌ans)

{

   if(last==0)

   ......

}

模拟题的特点:题目特烦,细节超多,代码极长(high level风格的调试的时间就比较少)

 

对于写代码的一些注意事项:

做题时尽量一遍A掉,不要利用OJ反复提交的益处,模拟考场时的一次提交的情况,防止未来考场爆零

 

 

暴力对拍:

1. 自己造数据

2. 对拍

贪心算法的数学原理即局部最优得到全局最优[大胆猜想,无需证明]

 

 

 

通过局部最优达到全局最优,需要满足两个条件:

1. 决策无后效性

2. 不会陷入局部最优解

贪心其实算是一种思路,一般来说用于求解最优化问题

 

 

 

贪心例题↑

先按价值排序,后取chocolate

 

 

首先我们考虑前缀和

然后加上一个数,加上一个数有两种情况:

   1.(x-y)%mod

2.(x+mod-y)%mod

可以借鉴一下set和map库

 

 

活动安排——是真的经典啊QwQ

我们按照活动结束时间排序,一个一个放就好了(我还写过。。。)

---------------------------------------------------------------------

#include<bits/stdc++.h>

using namespace std;

struct node

{

        int st,ed;

}a[1001];

bool cmp(node x,node y)

{

        return x.ed<y.ed;

}

int main()

{

        int n;

        cin>>n;

        for(int i=1;i<=n;i++)

        {

               cin>>a[i].st>>a[i].ed;

        }

        sort(a+1,a+n+1,cmp);

        int t=a[1].ed;

        int ans=1;

        for(int i=2;i<=n;i++)

        {

               if(a[i].st>=t)

               {

                       ans++;

                       t=a[i].ed;

               }

        }

        cout<<ans;

        return 0;

}

 

---------------------------------------------------------------------

大体就这样,反正主要就是排序以及贪心的思想

喷水装置:

 

 

这个也做过。。。

---------------------------------------------------------------------
#include<bits/stdc++.h>

using namespace std;

int n,cnt,L,h,x,r;

struct node

{

    double x,y;

}a[15001];

bool cmp(const node &x,const node &y)

{

    return x.x<y.x;

}

inline void Read()

{

    cin>>n>>L>>h;

    cnt=0;

    for(int i=1;i<=n;i++)

    {

        cin>>x>>r;

        if(r<=h/2) continue;

        cnt++;

        a[cnt].x=x-sqrt(r*r-h*h/4.0);

        a[cnt].y=x+sqrt(r*r-h*h/4.0);

    }

    sort(a+1,a+1+cnt,cmp);

}

inline void solve()

{

    double t=0;

    int ans=0,bj=1,i=1;

    while(t<L)//顺序扫描

    {                       

        ans++;

        double s=t;

        for(;a[i].x<=s&&i<=cnt;i++)//依次找到覆盖l的最大右端 

        if(t<a[i].y) t=a[i].y;

        if(t==s&&s<L)//无解判断 

        {

            cout<<0<<endl;

            bj=0;

            break;

        }                            

    }

if(bj)

{ 

    cout<<ans<<endl;

}

}

 

inline void clean()

{

        memset(a,0,sizeof(a));

}

 

int main()

{

    int T;

    cin>>T;

    while(T--)

    {

        Read();

        solve();

        clean();

    }

    return 0;

}

 

 

---------------------------------------------------------------------

一本通上有个问题就是说无解要输出0。。。(和题目所述不太一样)

主要按左边能覆盖的能盖到最右边的喷泉来排序,尽量用更少的喷泉

也是排序吧(大雾——主要得用到与草地的交点,大概可以看做线段吧qwq

 

 

按照岛屿为圆心,然后看与x轴的交点,看选出雷达可能存在的区间范围,然后区间选点就行了

 

 

(连老师看到都说骚。。。)

首先,先把杀掉能回血的先杀了。显然杀的顺序按照消耗升序杀完以后,不管用什么顺序杀掉剩下的怪,最后体力last是确定的。倒序来看,相当于将血药吐出来然后返还杀怪的消耗,那么显然也是按照损失体力(即血药回血量)升序,正回来即是降序。。。即分为两部分,杀完能回血的按照消耗升序,剩余按血药回血量降序,然后模拟一遍判断是否合法即可(科技为了我qwq)

 

 

1. 能把最大值调动到最前面(尽量前调)

2. 不能把最大值调动到最前面

 

 

rqy说:这题难度在高精qwq

将左手和右手的数成绩小的放在前面,主要是高精(不想写TAT)

下午考试:爆炸了qwq

T1

 

x+y+z=0

枚举x,y

看看有没有-z

把所有的数字排个序,枚举a[i],枚举a[j]

计算x=0-a[i]-a[j]

然后在排完序的数组里找x

保证a[i]<a[j]<x

在数组中可以运用类似二分的知识来AC改题。。。

T2

 

考虑用p来搞这个题,找循环节,然后就A了(大雾)

主要是中间的思想,若n>p,则必有一个 g(i)=g(j)[i<j]

那么就会有循环节出现,这样通过循环节来判断就更加的简单了

T3

 

整体分治

将棋盘分为两部分,进行分治(然后大雾TAT)

分为上下方,然后对于上方的(x1,y1),用长为m的01数组记录,

up[x1][y1][k]表示(x1,y1)是否能走到点(mid,k)

down[x2][y2][k]表示点(mid,k)是否能走到点(x2,y2)

求(x1,y1)是否能走到(x2,y2)只需要看是否存在一个i满足

up[x1][y1][i]==1&& down[x2][y2][i]==1

void 分治()

{

把棋盘劈成两半

计算预处理数组up

计算预处理数组down

把询问分成三部分:q1,q2,q3

q1,q2递归解决

q3用上述方法解决
}

up[i][j][k]= up[i+1][j][k]| up[i][j+1][k]

down[i][j][k]= down[i-1][j][k]| down[i][j-1][k]

 

posted @ 2019-07-13 20:40  卍GC卐  阅读(180)  评论(0编辑  收藏  举报