CodeTon Round 2 (Div. 1 + Div. 2, Rated, Prizes!)
\(\texttt{Rating Change:}\color{orange}{2213}\color{black}\to \color{orange}{2225}\)
\(\Delta={\color{green}{\texttt{12}}}\qquad \texttt{rank:510}\)
最近质量最高的一场 Chinese Round 吧。
A
可以转化成每次将前面两个中选一个留下。这样也就是说只有 \(b\) 的第一位可以和 \(a\) 相应的后缀不同。并且如果不同必须要是 \(a\) 此前出现过的。
My Code
using namespace std;
const int MAXN=55;
void solve(){
int n,m;cin>>n>>m;string a,b;
cin>>a>>b;a=' '+a;b=' '+b;
int ta=n,tb=m;
while(a[ta]==b[tb]&&tb>=1) ta--,tb--;
if(tb>1) cout<<"NO\n";
else if(tb==0) cout<<"YES\n";
else{
per(i,ta,1) if(a[i]==b[1]){
cout<<"YES\n";
return;
}cout<<"NO\n";
}
}
signed main()
{
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
int T;for(cin>>T;T--;)solve();
return 0;
}
B
一开始确定一个可选的 \(v\) 的区间,然后将这个区间不停地加上当前的限制。直到区间为空的时候,使用一次 change,然后继续这样做,显然是最少的。
My Code
#define int long long
using namespace std;
const int MAXN=2e5+10;
int a[MAXN];
void solve(){
int n,x;cin>>n>>x;
rep(i,1,n) cin>>a[i];
int l=a[1]-x,r=a[1]+x,ans=0;
rep(i,2,n){
if((a[i]-x>=l&&a[i]-x<=r)||(a[i]-x<l&&a[i]+x>=l))
l=max(l,a[i]-x),r=min(r,a[i]+x);
else ans++,l=a[i]-x,r=a[i]+x;
}cout<<ans<<'\n';
}
signed main()
{
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
int T;for(cin>>T;T--;)solve();
return 0;
}
C
相当于每次我们可以把一处感染堵上。这样我们把所有未感染的段全部取出来,从大到小贪心地去堵。实在太短,已经被感染的就摆,这样肯定能最大限度地救人。
My Code
#define int long long
using namespace std;
const int MAXN=1e5+10;
int a[MAXN];
void solve(){
int n,m;cin>>n>>m;
rep(i,1,m) cin>>a[i];
sort(a+1,a+1+m);
vector<int> cnt;
rep(i,2,m) cnt.pb(a[i]-a[i-1]-1);
cnt.pb(a[1]+n-a[m]-1);
sort(all(cnt));reverse(all(cnt));
int del=0,alv=0;
for(int v:cnt){
if(v-del>1) alv+=v-del-1,del+=4;
else if(v-del==1) del+=2,alv++;
else break;
}cout<<n-alv<<'\n';cerr<<'\n';
}
signed main()
{
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
int T;for(cin>>T;T--;)solve();
return 0;
}
D
挺智慧的题。考虑操作一和操作二的不同之处。如果我们对于每个数组构造一个键值:
这样子对于操作一键值是不变的,而操作二会加一。所以我们直接算出每个数组的 \(s\),取最大的,然后与其他的差就是最少的操作二的次数。
My Code
using namespace std;
const int MAXN=1e5+10;
unsigned ll a[MAXN];
void solve(){
int n,m,x,mxid=0;cin>>n>>m;
unsigned ll mx=0;
rep(i,1,n){
a[i]=0;
rep(j,1,m)
cin>>x,a[i]+=1ll*x*j;
if(a[i]>mx) mx=a[i],mxid=i;
}cout<<mxid<<' '<<a[mxid]-a[mxid==1?2:1]<<'\n';
}
signed main()
{
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
int T;for(cin>>T;T--;)solve();
return 0;
}
E
半路改题面差评。
发现如果每个点没有一个后继是 \(0\) 的话,就不会出现减一的点集变化或者加一的点集变化的情况。那我们就可以直接对每个点算贡献。
此时并不一定满足。但是我们可以发现,先暴力跑 \(n\) 次,可以使得这张图满足上述条件,就做完了。
My Code
#define int long long
using namespace std;
const int MAXN=1010;
const int MOD=998244353;
vector<int> e[MAXN],fr[MAXN];
int v[MAXN],cnt[MAXN],deg[MAXN];
void solve(){
int n,m;cin>>n>>m;
rep(i,1,n) cin>>v[i],e[i].clear(),fr[i].clear(),cnt[i]=deg[i]=0;
rep(i,1,m){
int x,y;cin>>x>>y;
e[x].pb(y);fr[y].pb(x);deg[x]++;
}
int ed=0;
rep(i,1,n) if(!siz(e[i])){ed=i;break;}
rep(Cnt,1,1000){
vector<int> x;
rep(i,1,n) if(v[i]) x.pb(i);
if(!siz(x)){
cout<<Cnt-1<<'\n';
return;
}for(int i:x){
v[i]--;
for(int s:e[i])
v[s]++;
}
}
queue<int> q;q.push(ed);cnt[ed]=1;
while(!q.empty()){
int x=q.front();q.pop();
for(int s:fr[x]) (cnt[s]+=cnt[x])%=MOD;
for(int s:fr[x])
if(--deg[s]==0)
q.push(s);
}
int ans=1000;
rep(i,1,n){
ans=(ans+cnt[i]*v[i]%MOD)%MOD;
}cout<<ans<<'\n';
}
signed main()
{
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
int T;for(cin>>T;T--;)solve();
return 0;
}
F
博弈论是我不会的东西。
首先可以发现如果 R
和 B
数量不相等,那么肯定是多的那一方赢了。因为起初两方肯定取 RB
或者 BR
。当没有红蓝相邻的时候,只能取自己的那种颜色了。此时就是谁多谁活得久。
所以现在只需要讨论一下两者颜色相同的情况。我们把每一段红蓝相间的拉出来,我们只需要考虑这些段的胜负即可。
利用 \(SG\) 函数和,令 \(SG(len)\) 表示长度为 \(len\) 的红蓝段的 \(SG\) 值。这样直接求是 \(O(n^2)\) 的。然后打表发现实际上在长度很长的时候是以 \(34\) 为一循环的,所以只要预处理前一段即可。
My Code
using namespace std;
const int MAXN=5e5+10;
int sg[155],ha[155];
void init(){
rep(i,2,150){
memset(ha,0,sizeof(ha));
rep(j,1,i-1) ha[sg[j-1]^sg[i-j-1]]=1;
while(ha[sg[i]]) sg[i]++;
}
}
void solve(){
int n;cin>>n;
string s;cin>>s;s=' '+s;
int cntr=0,cntb=0,ans=0;
rep(i,1,n) if(s[i]=='R') cntr++;else cntb++;
for(int l=1,r;l<=n;l=r){
r=l+1;while(r<=n&&s[r]!=s[r-1]) r++;
if(r==l+1) continue;
int tmp=r-l;
while(tmp>150) tmp-=34;
ans^=sg[tmp];
}
if(cntr>cntb||(cntr==cntb&&ans))
cout<<"Alice\n";
else cout<<"Bob\n";
}
signed main()
{
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
init();
int T;for(cin>>T;T--;)solve();
return 0;
}