\(Codeforces\) \(Round\) \(631\)
A.Dreamoon and Ranking Collection
题目大意:
\(n\)轮比赛,每轮比赛排名已经给出,还可以进行额外的\(m\)场比赛
问:所有比赛进行完后,最多可以收集到从\(1\)开始的多少个连续名次
题解:
用一个数组统计一下排名的出现情况,然后扫一遍添加\(m\)个缺失名次即可
代码:
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
int main(){
int i,j,k,n,a,x,t,s[105],ans,mmax;
scanf("%d",&t);
while(t--){
scanf("%d%d",&n,&x);
memset(s,0,sizeof(s));
ans=0;mmax=0;
for(i=1;i<=n;i++){scanf("%d",&a);s[a]=1;mmax=max(mmax,a);}
for(i=1;i<=mmax;i++){
if(s[i]){ans=i;continue;}
else if(s[i]==0&&x){x--;s[i]=1;ans=i;}
else if(s[i]==0&&x==0){ans=i;break;}
}
while(s[ans]==1)ans++;
ans+=x;
ans--;
printf("%d\n",ans);
}
return 0;
}
B. Dreamoon Likes Permutations
题目大意:
给出\(n\)和长度为\(n\)的一个数列,可将其分为左右两部分,问有多少种分法,使得左右两部分都为从\(1\)开始的一个排列。输出方案数以及全部方案。
题解:
从左往右和从右往左各扫一次,处理出数组\(l_1\)、\(l_2\),分别表示从第\(1\)位和第\(n\)位到第\(i\)位的所有数是否构成一个排列。然后枚举断点,如果左右两侧都是一个排列,那么当前断点就是一个方案,输出即可。
代码:
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
int t,n,a[200005],mmax,s1[200005],s2[200005],l1[200005],l2[200005];
void doit(){
int i,j;
mmax=0;
for(i=1;i<=n;i++){
mmax=max(mmax,a[i]);
s1[a[i]]++;
if(s1[a[i]]==1&&mmax==i)l1[i]=1;
else if(s1[a[i]]>=2)break;
}
mmax=0;
for(i=n;i>=1;i--){
mmax=max(mmax,a[i]);
s2[a[i]]++;
if(s2[a[i]]==1&&mmax==n-i+1)l2[i]=1;
else if(s2[a[i]]>=2)break;
}
}
int main(){
int i,j;
scanf("%d",&t);
while(t--){
scanf("%d",&n);
memset(s1,0,sizeof(s1));
memset(s2,0,sizeof(s2));
memset(l1,0,sizeof(l1));
memset(l2,0,sizeof(l2));
for(i=1;i<=n;i++){scanf("%d",&a[i]);}
doit();
int ans=0;
for(i=1;i<n;i++)
if(l1[i]&&l2[i+1])ans++;
if(ans==0)printf("%d\n",ans);
else{
printf("%d\n",ans);
for(i=1;i<n;i++)
if(l1[i]&&l2[i+1])
printf("%d %d\n",i,n-i);
}
}
return 0;
}
C. Dreamoon Likes Coloring
题目大意:
\(n\)个格子,\(m\)次染色次数,每次染色宽度为\(l_i\),颜色为\(i\)
后染的颜色会覆盖原来的颜色
求一种染色方案使得每个格子都有颜色并且最后每个颜色都要出现
若无方案则输出\(-1\)
题解:
1.每个颜色至少要占一个格子,那么在第\(i\)个颜色涂上去之前,必定有\(i-1\)个格子已经有颜色了,因此\(n-li<i-1\)时必定无解。
2.总长度\(<n\)时必定无解。
3.其他情况均为有解情况,为获得方案,只需先默认第i个颜色从第i个格子开始涂。然后再贪心的将部分颜色往后面挪以填充未染色的格子即可。
ps.代码中是从后往前图的颜色
代码:
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
typedef long long lol;
lol n,m,l[100005],sum,ans[100005];
int main(){
lol i,j;
scanf("%lld%lld",&n,&m);
for(i=1;i<=m;i++){scanf("%lld",&l[i]);sum+=l[i];}
for(i=1;i<=m;i++)
if(n-l[i]<i-1){
printf("-1\n");
return 0;
}
if(sum<n){
printf("-1\n");
return 0;
}
lol len=m+l[m]-1,need=n-len,place=n-l[m]+1;
for(i=m;i>=1;i--){
ans[i]=place;
if(need==0)place--;
else{
place-=min(l[i-1]-1,need)+1;
need-=l[i-1]-1;
if(need<0)need=0;
}
}
for(i=1;i<=m;i++)
printf("%d ",ans[i]);
printf("\n");
return 0;
}
D. Dreamoon Likes Sequences
题目大意:
对于每组数据给出两个整数\(d\)和\(m\)
求满足下列条件的数列\(a_n\)的个数对\(m\)取模的结果
1.\(1≤a_1<a_2<?<a_n≤d\)
2.\(a_n\)的前缀异或和\(b_n\)也为单调递增数列
题解:
由异或运算得到本题应从二进制角度来思考。
由异或和单调递增可知,数列\(a_n\)的最高位单调递增。
于是讨论二进制最高位的位数:
1.位数为\(1\)时,有\(1\)种
2.位数为\(2\)时,有\(2\)种
3.位数为\(3\)时,有\(4\)种
...(以此类推)
故答案为\(ans=(1+1)*(2+1)*(4+1)...-1\)
ps.\(+1\)是因为当前数可以不取,\(-1\)是因为要减去全部都不取的情况。
代码:
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
typedef long long lol;
lol n,mod,t;
int main(){
scanf("%lld",&t);
while(t--){
scanf("%lld%lld",&n,&mod);
lol ans=1%mod,x=1;
while(x<=n){
ans=(ans*(min(x,n-x+1)+1))%mod;
x<<=1;
}
ans--;
ans%=mod;
while(ans<0)ans+=mod;
printf("%lld\n",ans);
}
return 0;
}
E. Drazil Likes Heap
题目大意:
给定一个层数为\(h\)的满二叉大根堆,再给定一个整数\(g\)。
每次操作删除堆中的一个数。
求一个删除堆中元素的方案,使得:
1.最后得到的堆为一个\(g\)层的满二叉大根堆。
2.该堆的元素和最小。
输出最小的和以及删除方案。
题解:
不难得到以下结论:
1.每次删除一个节点,由它大儿子和大孙子组成的链的深度\(-1\)。
2.一个节点不可删,当且仅当它大儿子和大孙子等组成的链的深度等于\(g\)。
3.一个节点不可删,那么它的大儿子也不可删。由它大儿子和大孙子组成的链都不能删。
于是得到贪心算法,如果根节点能删则删,否则把左右儿子当作根分别进行删除操作。
这样能够保证随后得到的堆的元素和是最小的。
代码:
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#define ll(x) (x<<1)
#define rr(x) (x<<1|1)
using namespace std;
typedef long long lol;
int n,m,t,h,g,cnt,a[2500000],ans[2500000];
lol sum;
void del(int x){
if(a[ll(x)]==0&&a[rr(x)]==0)a[x]=0;
else{
if(a[ll(x)]>a[rr(x)]){
a[x]=a[ll(x)];
del(ll(x));
}
else{
a[x]=a[rr(x)];
del(rr(x));
}
}
}
int get_depth(int x,int depth){
if(a[x]==0)return depth-1;
if(a[ll(x)]>a[rr(x)])return get_depth(ll(x),depth+1);
else return get_depth(rr(x),depth+1);
}
void dfs(int x,int depth){
if(a[x]==0)return;
while(get_depth(x,depth)>m){del(x);ans[++cnt]=x;}
dfs(ll(x),depth+1);
dfs(rr(x),depth+1);
}
int main(){
int i;
scanf("%d",&t);
while(t--){
cnt=0;sum=0;
scanf("%d%d",&n,&m);
h=(1<<n)-1;g=(1<<m)-1;
for(i=1;i<=h*2+1;i++)a[i]=0;
for(i=1;i<=h;i++)scanf("%d",&a[i]);
dfs(1,1);
for(i=1;i<=g;i++)sum+=a[i];
printf("%lld\n",sum);
for(i=1;i<=cnt;i++)
printf("%d ",ans[i]);
printf("\n");
}
return 0;
}
BBT
没啥,就是觉得自己菜的一批
原文地址:https://www.cnblogs.com/huangdalaofighting/p/12637116.html