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]