您的位置:首页 > 其它

离线赛20171007总结

2017-10-07 16:22 190 查看

总结:

这份试卷其实不难,跟上次还是差不多的。但是这次只考了220,裸分差不多也就这分数。就是说这次发挥不算好也不算差。主要是第三题只得到了20分。这分还是太少了一些。但是因为第一题浪费了太多时间,后面的也就差不多没有多少时间。

题目解析:

1.S数

解析:这个题目其实找规律没有一些数学功底还是有些难推的。但是这毕竟不是数学考试,先暴力打了一个1到10000的表,得到的规律发现每一位上的数字都不会超过3。但是这个规律还是不足以支持直接前缀和,复杂度还是降不下来。一开始只会打80分暴力,后来发现这数非常少,就决定打表。打了80kb的表,然后二分,总算是过了。

 但是当时我在想的却是用0,1,2,3组合的数并不一定满足条件,就没继续往下想了。所以我当时只是想到利用这个结论来剪枝,没有想到深搜枚举。显然这个枚举的复杂度非常低,仅仅是4^9次方。枚举出来再判一下范围,判一下是否满足,就非常简单了。

2.黑客入侵

解析:一开始看这个题目就有了一些想法,那就是枚举备用坦克打掉的范围,复杂度是O(n)的,然后只要先预处理处前i个坦克互相攻击的损失,这里用一下二分查找,就可以以O(log(n))的复杂度处理出来,所以总的复杂度是O(nlog(n))的。这题应该还是比较简单的。

代码示范:

#include<bits/stdc++.h>
#define M 200005
using namespace std;
struct node{
int dis,pos,num;
}A[M];
int n,cnt[M],ans=2e9,L,R,mid,res;
bool check(int x,int y){
if(A[x].pos<y)return true;
else return false;
}
int main(){
cin>>n;
for(int i=1;i<=n;i++){
scanf("%d%d",&A[i].pos,&A[i].dis);
}
for(int i=1;i<=n;i++){
int m;
m=A[i].pos-A[i].dis;
L=0,R=i,res=0;
while(L<=R){
mid=(L+R)>>1;
if(check(mid,m)){
L=mid+1;
res=mid;
}
else R=mid-1;
}
cnt[i]+=cnt[res];
cnt[i]+=i-res-1;
}
for(int i=1;i<=n;i++){
if(ans>cnt[i]+n-i)ans=cnt[i]+n-i;
}
cout<<ans<<endl;
}


 其实这只是一种想法,还有其他神犇的想法非常精妙,可以去看看Shimakz的博客。

  

3.炮兵阵地

解析:这题我dfs写对了,但只有20分,其他大佬用了很神奇的剪枝就有40分,还不是时间超限!!一开始还用了很迷的写法,并查集和树形dp,可以把联通的并在一起。后来发现这个图并不满足树的形状和性质,所以用树形dp是错误的。在经历了一系列错误的想法之后,我就放弃选择dfs水分。我曾经注意到m<=10这个数据,但却没有什么想法。记得在刚学状压dp的时候就记笔记要观察数据,如果数据较小,并且状态可以用0,1表示的话,就要考虑一下状压dp。可惜当时没有想法。只能说我对于状压dp掌握的还不是很熟练。

  其实这个点能不能放,完全取决于上两层的状态。因为每一层的状态合法与否早就处理好了,所以不需要考虑横着的。那只要把上两层的状态记录下来,用dp递推下来。那么因为地图本来就很小,合法的状态也非常少,复杂度刚刚好。

  dp状态这样定义:dp[i][j][k]表示第i层的状态和i-1,i-2的状态最多可以安放的阵地数量。

反思:

这次主要的失分在第3题,这是因为我状压dp不熟练造成的。现在我要去复习(划水)一下了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: