预计得分:(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\%)的数据 ,(lenleq 20)。
对于(70\%)的数据,(lenleq 1000)。
对于(100\%)的数据,(lenleq 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,yin [1,n],x<y)
(x,y)中出现的([0,9])的数码种类相同。
输入格式1个整数 。
输出格式输出1个数即答案。
数据范围与约定
对于(30\%)的数据,(nleq 10^3)。
对于(100\%)的数据,(nleq 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
ot =a_2
所以对于任意$a_i,a_jin S$,都有$a_i
ot =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\%)的数据,(nleq 10^3)。
对于(70\%)的数据,(nleq 10^5)。
对于(100\%)的数据,(nleq 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;
}