10:26模拟赛
预计得分:\(100+30+30\)
实际得分:\(100+0+20\)
实实际得分:\(100+30+20\)
NOIP模拟赛
Reverse
题目描述
0比1小,所以1个串中如果0全在1前面,这个串就比较和谐。对于1个只包含
0和1的串,你每次可以将若干个0变成1,或者将若干个1变成0。那么,最少需要变多
少次才能把保证所有的0在1前⾯呢?
输入格式
一个01串。
输出格式
一个数即答案。
数据范围与约定
对于\(40\%\)的数据 ,\(len\leq 20\)。
对于\(70\%\)的数据,\(len\leq 1000\)。
对于\(100\%\)的数据,\(len\leq 10^5\)。
做法:枚举0和1交界的位置
利用前缀和统计答案。
因为太水所以2分钟就做完了第一题
#include<iostream>
#include<cstdio>
#define N 500005
using namespace std;
void read(int & s){
char ch=getchar();
for(;!isdigit(ch);ch=getchar());
for(s=0;isdigit(ch);s=s*10+ch-'0',ch=getchar());
}
int n;
int s[N],q[N];
int main(){
freopen("reverse.in","r",stdin);
freopen("reverse.out","w",stdout);
char ch=getchar();
for(;!isdigit(ch);ch=getchar());
for(;isdigit(ch);s[++n]=ch-'0',ch=getchar());
for(int i=1;i<=n;++i)
q[i]=q[i-1]+s[i];
int ans=0x3f3f3f3f;
int qqq=0;
for(int i=0;i<=n;++i){
qqq=0;
qqq+=q[i]+n-i-q[n]+q[i];
ans=min(qqq,ans);
}
printf("%d",ans);
return 0;
}
Number
题目描述
给定 ,求有多少数对\(<x,y>\)满足:
\(x,y\in [1,n],x<y\)
\(x,y\)中出现的\([0,9]\)的数码种类相同。
输入格式1个整数 。
输出格式输出1个数即答案。
数据范围与约定
对于\(30\%\)的数据,\(n\leq 10^3\)。
对于\(100\%\)的数据,\(n\leq 10^7\)。
做法:打表没打完而且代码只允许10KB而且只能过30%的数据
而且暴力都能打30分
所以这题打表失败了
本来想用组合数的相关内容做
但是不好维护而且代码应该会巨长巨恶心
就没写
正解思路:
首先统计出每个数其所有拥有数位的信息
因为产生<a,b>关系的数\(A,B\)其拥有的数码相同
这个可以通过下述方式达到
用\(S_n\)表示\(n\)的数位信息
则统计出所有数位相同的组数通过排列组合得出即可
我们设某一数位$S$的数量为$sum_S$,则易知$sum_S=C_{sum_S}^2$
因为每两个拥有数位S相同的数$a_1,a_2$
a_1\not =a_2
所以对于任意$a_i,a_j\in S$,都有$a_i\not =a_j$
所以总共的$<a_i,a_j>$的个数为$C_{sum_S}^2$
所以最终答案为$\sum_{i=1}^n C_{s_{S_i}}^2*s_{S_i}$
其中n为所以不同数位的个数
Wave
题目描述
给定一个长为\(n\)的数列,试求一个最长的不稳定波动子序列满足任意偶数项的
值不小于其相邻两项的值,且相邻两项的差不大于\(k\) 。
输入格式
输入第一行两个正整数 ;
第 n行 个非负整数描述这个数列。
输出格式
输出一个整数即答案。
数据范围及约定
对于\(30\%\)的数据,\(n\leq 10^3\)。
对于\(70\%\)的数据,\(n\leq 10^5\)。
对于\(100\%\)的数据,\(n\leq 2*10^6\), 数列中的数不超过\(2^{31}-1\)。
做法:\(O(n^2)dp\)
能过30的数据没问题
但是说好的\(30\%\)数据\(10^3\)
呢???怎么变\(10^5\)了……
这个做法可以用线段树优化
具体是用权值线段树维护
正解是贪心
考场上想到贪心
然后开始YY
有一段单增区间\([l,r]\)
答案应该存在于\([l,r]\)的两端才对
然后脑残的我竟然接着想如果\([l,r]\)中存在一个很低的点
亲手把我自己的假设抛弃了
2333
然后就抛弃了正解做法
考后写了两份代码
#include<iostream>
#include<cstdio>
#define N 2000007
#define inf 0x7fffffff
using namespace std;
int s[N];
int que[N];
inline int read() {
int x=0;
char c=getchar();
while(c<'0'||c>'9')c=getchar();
while(c<='9'&&c>='0')x=x*10+c-'0',c=getchar();return x;
}
int main(){
int n=read();
int k=read();
que[0]=inf;
int now=0;
for(int i=1;i<=n;++i)s[i]=read();
for(int i=1;i<=n;++i){
if(now&1){
if(s[i]>=que[now]+k)que[++now]=s[i];
if(s[i]<que[now])que[now]=s[i];
}
else {
if(s[i]+k<=que[now])que[++now]=s[i];
if(s[i]>que[now])que[now]=s[i];
}
}
printf("%d",now);
return 0;
}
#include<iostream>
#include<cstdio>
#define N 2000007
#define inf 0x7fffffff
using namespace std;
int n,k;
int s[N];
int que[N];
inline void read(int & s){
char ch=getchar();
for(;!isdigit(ch);ch=getchar());
for(s=0;isdigit(ch);s=s*10+ch-'0',ch=getchar());
}
int main(){
read(n);read(k);
int now=1;
que[0]=inf;
s[n+1]=inf;
for(int i=1;i<=n;++i)read(s[i]);
for(int i=1;i<=n;++i){
if(now&1){
while(s[i]+k>que[now-1]){
if(s[i]>que[now-1])que[now-1]=s[i];
i++;
}
while(s[i+1]<s[i]&&i<n)i++;
if(que[now-1]<s[i]+k||i==n+1){
break;
}
que[now]=s[i];++now;
}
else {
while(s[i]<que[now-1]+k){
if(s[i]<que[now-1])que[now-1]=s[i];
i++;
}
while(s[i+1]>s[i]&&i<n)i++;
if(s[i]<que[now-1]+k||i==n+1){
break;
}
que[now]=s[i];++now;
}
}
int ans=0;
printf("%d",now-1);
return 0;
}