Codeforces Round #631 Div. 2
比赛链接 https://codeforces.com/contest/1330
比赛记录 https://blog.csdn.net/cheng__yu_/article/details/105395197
A. Dreamoon and Ranking Collection(补数)
题意:给定数组,可以补充x次,问最多能够连续到哪个数
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=1e5+5,maxm=1e5+5;
const int mod=1e9+7,inf=0x7f7f7f7f;
int t,n,x;
int a[110];
int main()
{
cin>>t;
while(t--)
{
cin>>n>>x;
for(int i=1;i<=n;++i) cin>>a[i];
sort(a+1,a+1+n);
int total=unique(a+1,a+1+n)-a-1;
int now=0;
for(int i=1;i<=total;++i)
{
int need=max(0,a[i]-now-1);
if(x>=need)
{
x-=need;
now=a[i];
}
else
break;
}
now+=x;
cout<<now<<"\n";
}
return 0;
}
B. Dreamoon Likes Permutations(找排列)
题意:给定一个长度为 n 的数组,问能不能分成两个排列
思路:扫一遍数组,遇到第一个重复的数,即可分成两边分别判断前后两部分是不是排列。然后最多两个答案,前后各扫一遍即可
- 只有一个解的时候,前后扫到的是同一个答案,特判一下
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=2e5+5,maxm=1e5+5;
const int mod=1e9+7,inf=0x7f7f7f7f;
int t,n;
int a[maxn],b[maxn];
map<int,bool> m;
vector<pair<int,int> > ans;
bool check(int a[],int f)
{
m.clear();
int index=-1;
for(int i=1;i<=n;++i)
{
if(m.count(a[i]))
{
index=i-1;
break;
}
m[a[i]]=true;
}
sort(a+1,a+1+index);
int x=0;
for(int i=1;i<=index;++i)
if(a[i]!=i)
return false;
sort(a+1+index,a+1+n);
for(int i=index+1;i<=n;++i)
if(a[i]!=i-index)
return false;
if(f)
index=n-index;
ans.push_back({index,n-index});
return true;
}
int main()
{
cin>>t;
while(t--)
{
cin>>n;
for(int i=1;i<=n;++i)
cin>>a[i];
memcpy(b,a,sizeof(a));
reverse(b+1,b+1+n);
ans.clear();
check(a,false);
check(b,true);
if(ans.size()==2&&ans[0].first==ans[1].first)
ans.pop_back();
cout<<(int)ans.size()<<"\n";
for(auto it : ans)
cout<<it.first<<" "<<it.second<<"\n";
}
return 0;
}
C. Dreamoon Likes Coloring(贪心)
题意:给定 m 块木板,让它们覆盖长度为 n 的区间。需求最后每块木板必须有一个单位长度没有被覆盖。输出覆盖的方案
思路:先让每块木板只覆盖一个单位长度,然后右边肯定会有空余的位置,然后一块一块往右移动。
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=1e5+5,maxm=1e5+5;
const int mod=1e9+7,inf=0x7f7f7f7f;
int n,m;
int l[maxn],p[maxn];
int main()
{
scanf("%d%d",&n,&m);
bool valid=true;
ll sum=0;
for(int i=1;i<=m;++i)
{
scanf("%d",&l[i]);
p[i]=i;
sum+=l[i];
if(p[i]+l[i]-1>n)
valid=false;
}
if(!valid||sum<n)
{
puts("-1");
return 0;
}
p[n+1]=n+1;
for(int i=n;i>=1;--i)
{
if(p[i]+l[i]>=p[i+1])
break;
p[i]=p[i+1]-l[i];
}
for(int i=1;i<=m;++i)
printf("%d%c",p[i],i==n?'\n':' ');
return 0;
}
D. Dreamoon Likes Sequences(递推)
题意:翻译过来就是: 第一个位置只能填 1 ,第二个位置能填 2、3,第三个位置能填4、5、6、7,依次类推,问最终满足条件的方案数
思路:递推:填到第 i 位时,该位能填的数有
2
i
−
1
2^{i-1}
2i−1,那么增加的答案就是
a
i
−
1
×
(
2
i
−
1
+
1
)
+
2
i
−
1
a_{i-1}\times(2^{i-1}+1)+2^{i-1}
ai−1×(2i−1+1)+2i−1
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=1e3+10,maxm=1e5+5;
const int inf=0x7f7f7f7f;
int t;
ll d,mod,a[100];
int main()
{
cin>>t;
while(t--)
{
cin>>d>>mod;
int cnt=-1;
ll n=d;
while(n)
{
cnt++;
n>>=1;
}
a[1]=1;
for(int i=2;i<=cnt;++i)
{
ll x=1<<i-1;
a[i]=(a[i-1]*(x+1)%mod+x)%mod;
}
ll r=d-(1<<cnt)+1;
ll ans=(a[cnt]*(r+1)%mod+r)%mod;
cout<<ans<<"\n";
}
return 0;
}
E. Drazil Likes Heap
#include <bits/stdc++.h>
#define ll long long
#define ls (rt<<1)
#define rs ((rt<<1)|1)
using namespace std;
const int maxn=(1<<21)+10;
int t,h,g;
int a[maxn];
int leaf(int rt)
{
if(!a[ls]&&!a[rs])
return rt;
if(a[ls]>a[rs])
return leaf(ls);
else
return leaf(rs);
}
void del(int rt)
{
if(!a[ls]&&!a[rs])
a[rt]=0;
else if(a[ls]>a[rs])
{
a[rt]=a[ls];
del(ls);
}
else
{
a[rt]=a[rs];
del(rs);
}
}
int main()
{
scanf("%d",&t);
while(t--)
{
vector<int> ans;
scanf("%d%d",&h,&g);
int n=(1<<h)-1;
ll sum=0;
for(int i=1;i<=n;++i)
scanf("%d",&a[i]),sum+=a[i];
for(int i=n+1;i<(1<<h+1);++i)
a[i]=0;
int limit=(1<<g)-1;
for(int i=1;i<=limit;++i)
{
while(leaf(i)>limit)
{
ans.push_back(i);
sum-=a[i];
del(i);
}
}
printf("%lld\n",sum);
for(auto i: ans)
printf("%d ",i);
puts("");
}
return 0;
}