目录
1、饮料换购(15年省赛)
简单模拟题
#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
#define MOD 1000000009
using namespace std;
typedef long long LL;
int n,s;
int main() {
cin>>n;
int nn=n;
while(n>=3) {
s++;
n-=2;
}
cout<<s+nn;
return 0;
}
2、密文搜索(15年国赛)
标签是数学题,可是我更偏向于是模拟题兼一点排序成分。
资料的顺序不能改变,密码的顺序是打乱的,那么我们就直接使用sort将这些密码一次性排个序,然后用map来存值,最后将实际的密码和可能是密码的密码进行比对算出匹配次数的总和
#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
#define MOD 1000000009
using namespace std;
typedef long long LL;
string s,s1;
int n;
LL ans;
map<string,int> mp;
int main() {
cin>>s;
//给定的资料的顺序不能改变,最后的密码当然是后八位啦
for(int i=0; i+7<s.size(); i++) {
string s2;
for(int j=i; j<=i+7; j++)//每次要8个字母当密码
s2+=s[j];//将密码放到变量中来存值
sort(s2.begin(),s2.end());//将可能出现的密码进行排序用于后续存储
mp[s2]++;//利用map的性质来对可能出现的密码进行存值
}
cin>>n;
while(n--) {
cin>>s1;
sort(s1.begin(),s1.end());//密码是打乱的,需要排一下序
ans+=mp[s1];
}
cout<<ans;
return 0;
}
3、蓝桥骑士
解析:
这是一道LIS(最长上升子序列)模板题,毫无疑问,我们会和LCS联想在一起,也就是说我们会使用DP来做,但是DP的时间复杂度是O(n^2),在这里是9*10^10,超时,所以这道题不能用dp做。
我们应该用二分+贪心来做,由于它只需要我们求最长上升子序列长度,而非具体元素,那么我们就可以用一个low数组来进行维护,博主刚学最长上升子序列,不知如何表达.详情请看
下面有DP和二分贪心做法
/*O(n^2)朴素做法
#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
#define MOD 1000000009
using namespace std;
typedef long long LL;
LL f[300010],n;
LL a[300010],maxn;
int main() {
cin>>n;
for(int i=1; i<=n; i++) {
cin>>a[i];
f[i]=1;
}
for(int i=1; i<=n; i++)
for(int j=1; j<i; j++) {
if(a[i]>a[j]) f[i]=max(f[i],f[j]+1);
}
for(int i=1; i<=n; i++)
maxn=max(maxn,f[i]);
cout<<maxn;
return 0;
}*/
//二分+贪心
//low序列并不一定表示最长上升子序列,它只表示相应最长子序列长度的排好序的最小序列
#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
#define MOD 1000000009
using namespace std;
typedef long long LL;
int low[300010],a[300010];
int n,ans;
int main() {
cin>>n;
for(int i=1; i<=n; i++) {
cin>>a[i];
low[i]=INF;
}
low[1]=a[1];//初始化第一个数
ans=1;
for(int i=2; i<=n; i++) {
if(a[i]>low[ans]) //大于就在low中增加
low[++ans]=a[i];//进low数组
else {
//lower_bound找到的点的位置是low+x,即low中第x个位置
int j=lower_bound(low+1,low+ans+n,a[i])-low;
low[j]=a[i];//和大于等于a[i]的第一个元素的位置互换
}
}
cout<<ans;
return 0;
}