这次比赛还是暴露出了自己的一些不足之处,比如比赛经验以及心态,还有某些知识点的缺失等等
总的来说发挥正常,就是第二题越做越慌,但是最后还是克服了这一心态,还是非常不错的
以后开始慌了就上厕所
样例输入
5
2
1
2
2
3
样例输出
2
数据范围
对于20%的数据,n <= 10
对于40%的数据,n <= 1000
对于60%的数据,n <= 10000
对于100%的数据,1 <= n <= 10^6
这个题属于一眼题,但是很多人都会想到贪心,我开始也想的贪心:从大到小排序,然后尽量选大的。
这个贪心在测试的时候确实可以拿到80分,但是实质上是错误的,观察下面的数据:
10
1 1 1 3 6 6 6 6 6 6
如果贪心,分法就为:[1][113][666666]一共3组,但是实际上我们还有更优的方法:[1][1][1][3666666]一共4组,因此普通的贪心就是错的(当然改良版贪心是可以过的,不过不知道怎么写)
既然贪心不行,那么就试试分组DP,显然DP是可以过的
f[i]表示使得前i个人分组合法的组数最大值,f[i]=min{f[k]}+1 0<=k<=i-s[i]
但是不加任何优化的DP是拿不了满分的,显然复杂度为O(N^2)
f[i]=g[i–s[i]]+1;
g[i]=max(g[i-1],f[i]);
可以看到用g数组优化了f数组
#include
#include
#include
#include
using namespace std;
const int maxn=1e6+5,inf=x3f3f3f3f;
inline void _read(int &x){
char t=getchar();bool sign=true;
while(t<'0'||t>'9')
{if(t=='-')sign=false;t=getchar();}
for(x=0;t>='0'&&t<='9';t=getchar())x=x*10+t-'0';
if(!sign)x=-x;
}
int n,f[maxn],s[maxn],g[maxn];
int main(){
_read(n);
int i,j,cur;
for(i=1;i<=n;i++)_read(s[i]);
sort(s+1,s+1+n);
for(i=1;i<=n;i++){
if(ii-1)cur=i-1;
f[i]=g[cur]+1;
g[i]=max(g[i-1],f[i]);
}
cout<
输入样例
2 3
2 5 1
6 3 4
输出样例
6
4
5
1
1
1
数据范围
对于30%的数据,1<=N, M<=50;
对于全部的数据,1<=N, M<=300。
看到这题想到了无数做法但是都写不来,暴力的暴力都是O(N^6)
其实我们将矩阵看成1维线段就是一个广告印刷模型了,只要枚举矩阵上下界然后用一个数组保存下界每一列的最小值
接下来依次考虑min中每个元素作为子矩阵的最小值元素时,可以向左和向右扩展到多远。
以向右扩展为例。某一列k的最小值min[k]不会影响k左边比它小的元素向右扩展,但会影响左边比它大的元素向右扩展,用一个单调栈维护一个上升序列,可以高效处理。
#include
#include
#include
#include
using namespace std;
const int maxn=305,inf=0x3f3f3f3f;
int n,m,s[maxn][maxn],miny[maxn],ans[maxn*maxn],L[maxn],R[maxn];
stackq;
inline void _read(int &x){
char t=getchar();bool sign=true;
while(t<'0'||t>'9')
{if(t=='-')sign=false;t=getchar();}
for(x=0;t>='0'&&t<='9';t=getchar())x=x*10+t-'0';
if(!sign)x=-x;
}
int main(){
_read(n);_read(m);
int i,j,k;
for(i=1;i<=n;i++)
for(j=1;j<=m;j++)_read(s[i][j]);
for(i=1;i<=n;i++){
memset(miny,inf,sizeof(miny));
for(j=i;j<=n;j++){
for(k=1;k<=m;k++)miny[k]=min(miny[k],s[j][k]);
for(k=1;k<=m;k++){
while(q.size()&&miny[k]
样例输入
5
样例输出
3
样例解释
(1,1) → (1,2) → (3,2) → (5,2)
数据范围
对于30%的数据, 1 <= n <= 1000
对于60%的数据, 1 <= n <= 20000
对于100%的数据,1 <= n <= 10^6
这题爆搜加斐波拉契数列优化可以过70分,一神人同学用爆搜+rand骗分过了90分……
正解是类似于GCD的递归求解,其实说了正解就很简单了,注意一下边界处理即可
#include
#include
using namespace std;
const int inf=0x3f3f3f3f;
int n,ans;
int Div(int x,int y){
if(y==1)return x-1;
if(x==0||y==0||x==y)return inf;
return Div(y,x%y)+x/y;
}
int main(){
cin>>n;
ans=n-1;
for(int i=2;i
最后再说两句:
还是趁着最后几个星期补一下遗忘的知识点,小分绝不能丢!