C. Best Binary String
看一下例子不难发现
成本最少就是让1与1之间夹的0的次数最少,也就是1?1这种要变1,0?0这种要变0,1?变1,其他情况随意即可,简单推导得出:?前面是什么就变成什么;
代码如下:
#include<iostream>
#include<algorithm>
#include<set>
#include<vector>
#include<queue>
#include<cmath>
#include<cstring>
#include<cstdio>
#include<ctime>
#include<map>
#include<stack>
using namespace std;
#define int long long
const int N=2e5+10;
signed main()
{
int t;
cin>>t;
string s;
while(t--)
{
cin>>s;
int n=s.size();
if(s[0]=='?')
s[0]='0';
for(int i=1;i<n;++i)
{
if(s[i]=='?')
{
if(s[i-1]=='1')s[i]='1';
else s[i]='0';
}
}
cout<<s<<endl;
}
return 0;
}
D. Bracket Coloring
最多只有两种颜色,先判断字符串本身能否成为完美字符,如果可以直接输出1,否则
先把能组成括号对的标成1,剩下的为2就可以了
代码如下:
#include<iostream>
#include<algorithm>
#include<set>
#include<vector>
#include<queue>
#include<cmath>
#include<cstring>
#include<cstdio>
#include<ctime>
#include<map>
#include<stack>
using namespace std;
#define int long long
const int N=2e5+10;
int c[N];
signed main()
{
int n,t;
cin>>t;
string s;
while(t--)
{
cin>>n>>s;
stack<int>r,v;
int a=0,b=0;
for(int i=0;i<n;++i)
{
c[i]=0;
if(s[i]=='(')a++;
else b++;
}
if(a!=b)
{
cout<<-1<<endl;
continue;
}
a=b=0;
int fg=0,ff=0;
for(int i=n-1;i>=0;--i)
{
if(s[i]=='(')r.push(i);
else if(r.size())
{
r.pop();
}
else
{
ff=1;break;
}
}
if(!ff)
{
cout<<1<<endl;
for(int i=0;i<n;++i)cout<<1<<" ";
cout<<endl;
continue;
}
for(int i=0;i<n;++i)
{
if(s[i]=='(')r.push(i);
else if(r.size())
{
fg=1;
int pos=r.top(); r.pop();
c[i]=c[pos]=1;
}
}
if(!fg)
{
cout<<1<<endl;
for(int i=0;i<n;++i)
{
cout<<1<<" \n"[i==n-1];
}
continue;
}
else
{
int f=1;
for(int i=0;i<n;++i)
{
if(c[i]!=1)
{
f=2;
break;
}
}
cout<<f<<endl;
for(int i=0;i<n;++i)
{
if(c[i]!=1)cout<<2<<" ";
else cout<<c[i]<<" ";
}
cout<<endl;
}
}
return 0;
}
E. Playoff Fixing
这个题我想了很久,最后看了知乎大佬的代码写的,链接在这Educational Codeforces Round 149 (Rated for Div. 2) A ~ E - 知乎 (zhihu.com)
先捋下题意:ai为-1时表示i位置的数未确定,然后每轮比赛都会淘汰掉一半的人。
这里建议i把它看成变数哈,就是比如a2<a1,然后下一轮,a2就在1的位置上,也就是变成a1
思路:
每轮淘汰的人只能后半数字的人被淘汰,那么淘汰的人是确定的,设这轮未确定的后半数x,那么x个数可以选择放的x个位置就有x!的选择,然后每个被淘汰的数必须各自独立在不同的比赛中,如果该比赛的两个数都是-1,-1,则要×2,设这轮有y个该的比赛,那么该轮的贡献就为x!2^y;
代码如下:
#include <bits/stdc++.h>
#include<vector>
using namespace std;
#define int long long
const int N=2e6+10,mod=998244353;
int p[N];
int ksm(int x,int n)
{
int sum=1;
int a=x;
while(n)
{
if(n&1)sum=sum*a%mod;
a=a*a%mod;
n>>=1;
}
return sum%mod;
}
void init()
{
p[0]=1;
for(int i=1;i<=2e6;++i)
{
p[i]=p[i-1]*i%mod;
}
}
int solve(int n, vector <int> a)
{
if(n==0)return 1;
vector<int>b(1,0);
int y=0,x=(1ll<<(n-1));
for(int i=1;i<=(1ll<<n);i+=2)
{
if(a[i]>a[i+1])swap(a[i],a[i+1]);
if(a[i]==-1&&a[i+1]==-1)
{
++y;
b.push_back(-1);
}
else if(a[i]==-1)
{
if(a[i+1]<=(1<<(n-1)))
{
b.push_back(a[i+1]);
}
else
{
x--;
b.push_back(-1);
}
}
else if(a[i]>(1<<(n-1)))
{
return 0;
}
else if(a[i+1]<=(1<<(n-1)))return 0;
else
{
x--;
b.push_back(a[i]);
}
}
return p[x]*ksm(2,y)%mod*solve(n-1,b)%mod;
}
signed main()
{
int k;
init();
cin>>k;
vector<int>a((1<<k)+10);
for(int i=1;i<=(1<<k);++i)cin>>a[i];
int xx=solve(k,a);
cout<<xx;
}
F. Editorial for Two
这个题是看知乎的大佬写的,发现思路居然这么简单!链接在这
Educational Codeforces Round 149 (Rated for Div. 2) A - F - 知乎 (zhihu.com)
思路:
用二分写个函数ck,然后在里面写个循环找i左右两边选的数,两边的个数尽可能选大,最后只要相加>=k就行了
#include<iostream>
using namespace std;
#include<vector>
#include<queue>
#define int long long
const int N=2e6+10;
int n,a[N],k;
bool ck(int x)
{
priority_queue<int>r1,r2;
vector<int>c(n+1);
int sum=0;for(int i=1;i<=n;++i)
{
r1.push(a[i]);
sum+=a[i];
while(sum>x&&r1.size())
{
sum-=r1.top();
r1.pop();
}
c[i]=r1.size();
}
if(c[n]>=k)return true;
sum=0;
for(int i=n;i>=1;--i)
{
r2.push(a[i]);
sum+=a[i];
while(sum>x&&r2.size())
{
sum-=r2.top();
r2.pop();
}
if(r2.size()+c[i-1]>=k)return true;
}
return false;
}
signed main()
{
int t;
cin>>t;
while(t--)
{
cin>>n>>k;
int ans=0;
for(int i=1;i<=n;++i)
{
cin>>a[i];
ans+=a[i];
}
int l=1,r=ans;
while(l<r)
{
int mid=(l+r)/2;
if(ck(mid))
{
r=mid;
}
else l=mid+1;
}
cout<<r<<endl;
}
return 0;
}
第一次补完div2的题,在这里留个纪念记录一下,希望有一天我自己能在比赛中写完这些题。