rt,贪心爆改,树状数组加二分寻找最近的有色格子,然后根据中间空格子中小 R 的数量进行决策,赛时满分,但我不知道怎么解释正确性,所以希望 hack。
#include<bits/stdc++.h>
#define int long long
#define mod 998244353
using namespace std;
int s[1000009];
struct st{
int x;
bool s;
}q[1000009];
bool cmp(st a1,st a2){
return a1.x<a2.x;
}
struct stt{
int f[1000009];
int lowbit(int x){
return x&(-x);
}
void push(int x){
while(x<=1000000){
f[x]++;
x+=lowbit(x);
}
}
int q(int x){
int ans;
ans=0;
while(x){
ans+=f[x];
x-=lowbit(x);
}
return ans;
}
int que(int l,int r){
return q(r)-q(l-1);
}
}c;
int ss[1000009];
signed main(){
int n,m;
cin>>n>>m;
s[0]=2;
s[n+1]=2;
for(int i=1;i<=n;i++){
char t;
cin>>t;
if(t=='_'){
s[i]=2;
}else if(t=='B'){
s[i]=0;
}else{
s[i]=1;
}
if(t!='_'){
c.push(i);
}
}
for(int i=1;i<=m;i++){
char t;
cin>>t;
if(t=='R'){
q[i].s=1;
}else{
q[i].s=0;
}
cin>>q[i].x;
ss[q[i].x]=q[i].s;
}
for(int i=1;i<=n;i++){
ss[i]+=ss[i-1];
}
for(int i=1;i<=m;i++){
if(n==m&&i==1){
c.push(q[i].x);
s[q[i].x]=0;
}else{
int l,r;
l=1,r=n;
while(l<r){
int mid;
mid=l+r;
mid>>=1;
int s1,s2;
s1=q[i].x-mid;
s2=q[i].x+mid;
s1=max(s1,1ll);
s2=min(s2,n);
if(c.que(s1,s2)){
r=mid;
}else{
l=mid+1;
}
}
int s1,s2;
s1=q[i].x-l;
s2=q[i].x+l;
s1=max(s1,1ll);
s2=min(s2,n);
if(c.que(s1,q[i].x)){
if((ss[q[i].x]-ss[s1])&1){
s[q[i].x]=1-s[s1];
}else{
s[q[i].x]=s[s1];
}
}else{
if((ss[s2-1]-ss[q[i].x-1])&1){
s[q[i].x]=1-s[s2];
}else{
s[q[i].x]=s[s2];
}
}
c.push(q[i].x);
}
}
int ans;
ans=0;
for(int i=1;i<=n;i++){
if(s[i]!=s[i-1]){
ans++;
}
}
cout<<ans;
return 0;
}