https://codeforces.com/contest/1392/problem/D
sb题写了一年,写的巨复杂
把入度为1的不合法的点拿出来讨论就行了,如果两个相邻的都是不合法的,直接换一条边改两个,否则就该当前这个不合法的边
有更简单的写法,直接把连续的L或R拿出来,长度/3就行了
我的代码就别看了,写得巨丑
#include<bits/stdc++.h>
#define pb push_back
using namespace std;
typedef long long ll;
const int maxl=4e5+10;
int n,m,cas,k,cnt,tot,ans;
int a[maxl],b[maxl],rudu[maxl];
char s[maxl],ch[maxl];
int in[maxl][2],out[maxl][2];
inline int id(int x)
{
if(x<1) return n+x;
if(x>n) return x-n;
return x;
}
inline void prework()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
in[i][0]=in[i][1]=out[i][0]=out[i][1]=0;
rudu[i]=0;
}
scanf("%s",ch+1);
int st=1;ch[n+1]='0';
while(ch[st]==ch[st+1])
st++;
if(st+1>n)
st=0;
cnt=0;
for(int i=st+1;i<=n;i++)
s[++cnt]=ch[i];
for(int i=1;i<=st;i++)
s[++cnt]=ch[i];
for(int i=1;i<=n;i++)
{
if(s[i]=='L')
{
in[id(i-1)][1]=i,out[i][0]=id(i-1);
rudu[id(i-1)]++;
}
else
{
in[id(i+1)][0]=i;out[i][1]=id(i+1);
rudu[id(i+1)]++;
}
}
}
inline bool sb(int i)
{
if(rudu[i]!=1)
return false;
if(in[i][0] && s[i]=='L')
return false;
if(in[i][1] && s[i]=='R')
return false;
return true;
}
inline void mainwork()
{
ans=0;int l,r=0;char c,rc;
for(int i=1;i<=n;i++)
if(sb(i) )
{
ans++;
if(sb(id(i+1)))
{
if(s[i]=='L')
{
in[i][1]=0;rudu[i]--;
s[id(i+1)]='R';
in[id(i+2)][0]=id(i+1);rudu[id(i+2)]++;
}
else
{
in[id(i+2)][0]=0;rudu[id(i+2)]--;
s[id(i+1)]='L';
in[i][1]=id(i+1);rudu[i]++;
}
}
else
{
if(in[i][0] && s[i]!='L')
{
s[i]='L';
rudu[id(i+1)]--;in[id(i+1)][0]=0;
rudu[id(i-1)]++;in[id(i-1)][1]=i;
}
else if(in[i][1] && s[i]!='R')
{
s[i]='R';
rudu[id(i-1)]--;in[id(i-1)][1]=0;
rudu[id(i+1)]++;in[id(i+1)][0]=i;
}
}
}
}
inline void print()
{
printf("%d\n",ans);
}
int main()
{
int t=1;
scanf("%d",&t);
for(cas=1;cas<=t;cas++)
{
prework();
mainwork();
print();
}
return 0;
}