Codeforces Round #637 Div. 2
A.Nastya and Rice
题意:
给你五个数
n
,
a
,
b
,
c
,
d
n,a,b,c,d
n,a,b,c,d.
表示让你找出
n
n
n个数,每个数的范围是
[
a
−
b
,
a
+
b
]
[a-b,a+b]
[a−b,a+b],问能不能找出这样一个数组,使得总和在
[
c
−
d
,
c
+
d
]
[c-d,c+d]
[c−d,c+d].
题解:
判断一下
n
n
n个最大值的和是否小于
c
−
d
c-d
c−d,
n
n
n个最小值的和是否大于
c
+
d
c+d
c+d即可
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int t,n,a,b,c,d;
void solve(){
scanf("%d",&t);
while(t--){
scanf("%d%d%d%d%d",&n,&a,&b,&c,&d);
if(n*(a-b)>(c+d)||n*(a+b)<(c-d)) printf("No\n");
else printf("Yes\n");
}
}
int main(void)
{
solve();
return 0;
}
B.Nastya and Door
题意:
给定一个长度为n的数组,让你找出一个长度为k的子数组,这个子数组的山峰的数量最多,满足
a
[
i
−
1
]
<
a
[
i
]
,
a
[
i
]
>
a
[
i
+
1
]
a[i-1]<a[i],a[i]>a[i+1]
a[i−1]<a[i],a[i]>a[i+1]的i即为山峰,输出最小的左端点的值.
题解:
先预处理出关于山峰数量的前缀和,然后暴力即可
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAX = 2e5+5;
const int INF = 0x3f3f3f3f;
int t,n,k,a[MAX],sum[MAX],mx,mj;
bool vis[MAX];
void solve(){
scanf("%d",&t);
while(t--){
scanf("%d%d",&n,&k);
mx=-INF;
for(int i=1;i<=n;++i) vis[i]=false,sum[i]=0;
for(int i=1;i<=n;++i) scanf("%d",&a[i]);
for(int i=2;i<n;++i) if(a[i]>a[i-1]&&a[i]>a[i+1]) vis[i]=true;
for(int i=1;i<=n;++i) sum[i]=vis[i]+sum[i-1];
for(int i=1;i<=n-k+1;++i){
int num = max(0,sum[i+k-2]-sum[i]);
if(num+1>mx) mx=num+1,mj=i;
}
printf("%d %d\n",mx,mj);
}
}
int main(void)
{
solve();
return 0;
}
C.Nastya and Strange Generator
题意:
给定一个长度为n的排列,问经过题目中给出的算法流程,能否生成这样的排列.
算法流程为:
假定给出一个
[
2
,
3
,
x
,
x
,
1
]
[2,3,x,x,1]
[2,3,x,x,1].下一步的话就是要计算出4填入的位置
计算出r数组为
[
3
,
3
,
3
,
4
,
x
]
[3,3,3,4,x]
[3,3,3,4,x]. r数组的意义为当前节点开始往右数第一个未知元素的位置
然后计算出count数组
[
0
,
0
,
3
,
1
,
0
]
[0,0,3,1,0]
[0,0,3,1,0], count数组的意义为r数组中数字的个数.
然后现在count最大值的位置是3,所以往原数组3这个位置填入4,假如有多个最大值,则任意选择一个.
题解:
其实看样例都可以看出来规律了.
当填入数字
i
+
1
i+1
i+1时,当这个数组形如
[
x
,
x
,
x
,
1
,
2..
i
]
[x,x,x,1,2..i]
[x,x,x,1,2..i]这样填入的和未填入的位置没有交错时,数字
i
+
1
i+1
i+1可以任意填入一个位置.
反之,只能填入
p
o
s
[
i
]
+
1
pos[i]+1
pos[i]+1的位置,
p
o
s
[
i
]
pos[i]
pos[i]为数字i所在的位置.
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAX = 1e5+5;
const int INF = 0x3f3f3f3f;
int t,n,a[MAX],mx[MAX],idx[MAX];
bool flag;
void solve(){
scanf("%d",&t);
while(t--){
scanf("%d",&n);flag=true;
for(int i=1;i<=n;++i) scanf("%d",&a[i]),idx[a[i]]=i;
for(int i=n;i>=1;--i) mx[i]=max(mx[i+1],a[i]);
for(int i=1;i<=n;++i){
if(mx[idx[i]]==i) continue;
else if(idx[i]+1==idx[i+1]) continue;
else{ flag=false;break; }
}
for(int i=1;i<=n;++i) mx[i]=0;
printf("%s",flag?"Yes\n":"No\n");
}
}
int main(void)
{
solve();
return 0;
}
D.Nastya and Scoreboard
题意:
给你n段数码管,然后让你再点亮
k
k
k个数码位,问最大数字是多少
题解:
c
n
t
[
i
]
[
j
]
cnt[i][j]
cnt[i][j]代表i这个数到数字j需要点亮多少个数码位.
直接dfs爆搜.
从第一个数码管开始遍历,每个数码管枚举
9
−
0
9-0
9−0.
但是这样会超时,需要加上一点剪枝.
需要记录一个
v
i
s
vis
vis数组,
v
i
s
[
i
]
[
j
]
vis[i][j]
vis[i][j]表示第i个数码管剩下j次操作是否可行,不可行则为
f
a
l
s
e
false
false.
每次
d
f
s
dfs
dfs记录一下当前还剩下多少次操作即可
#include<bits/stdc++.h>
using namespace std;
const int MAX = 1e4+5;
const int INF = 0x3f3f3f3f;
string s[10]={ "1110111", "0010010", "1011101", "1011011", "0111010", "1101011", "1101111", "1010010", "1111111", "1111011"};
string lis[MAX],ans="",temp="";
bool vis[2005][2005];
int a[8],cnt[MAX][10],n,k;
void init(int index){
if(index==7){
int num=0;
for(int i=6,j=0;i>=0;--i,++j) num+=a[i]*(1<<j);
for(int i=0;i<=9;++i){
int count=0;
bool flag=true;
for(int j=0;j<7;++j){
if(a[j]==1&&s[i][j]=='0'){
cnt[num][i]=INF;
flag=false;
break;
}
else if(a[j]==0&&s[i][j]=='1'){
++count;
}
}
if(flag){
cnt[num][i]=count;
}
}
return;
}
a[index]=0;
init(index+1);
a[index]=1;
init(index+1);
}
bool dfs(int index,int k){
if(ans!="") return true;
if(index==n){
if(k!=0) return false;
for(int i=0;i<n;++i) ans+=temp[i];
return true;
}
if(!vis[index][k]) return false;
int num=0;
for(int i=6,j=0;i>=0;--i,++j) num+=(lis[index][i]-'0')*(1<<j);
bool f=false;
for(int i=9;i>=0;--i){
temp[index]=(char)(i+'0');
if(cnt[num][i]==INF||cnt[num][i]>k) continue;
bool v=dfs(index+1,k-cnt[num][i]);
vis[index+1][k-cnt[num][i]]=v;
if(v) f=true;
}
return f;
}
void solve(){
init(0);
scanf("%d%d",&n,&k);
for(int i=1;i<=n;++i) temp+="0";
for(int i=0;i<=2000;++i)
for(int j=0;j<=2000;++j)
vis[i][j]=true;
for(int i=0;i<n;++i) cin>>lis[i];
dfs(0,k);
if(ans=="") ans="-1";
cout<<ans;
}
int main(void)
{
solve();
return 0;
}