题解:P13274 [NOI2025] 三目运算符
大家好,不知道场内还是场外人员前来写题解。
场上最后
先考虑只有
考虑
让我们再来看一个比较普通的情况,整个串的每个
在两个
1 的连续段相隔一个0 以上时,前面一个串将会向后扩张,不断加上一个1 ;
当相隔一个0 时,这个0 将会跟后面的那个1 交换位置,视觉上就是这个0 向后移了一位,也可以说是前面的1 的连续串继续扩张,后面那个1 的连续段整体向后平移了一位。
经过与这样的模拟,我们不难发现其实要到达无法改变的状态(即不动点),取决于最开始的那个
当然我们还没有考虑只是
综上,我们可以得出的结论是:
- 如果存在
\texttt{110} ,记这个0 的位置为t ,那么答案就是n-t+1 。 - 如果不存在
\texttt{110} ,若存在\texttt{101} ,那么答案为1 。 - 否则答案为
0 。
所以我们只要维护第一个
至于区间反转,再记录一下
码还没写,写完了贴出来,退役久了估计这个题得写个两三个小时的,快进到题解通道关了。
时间复杂度
upd 2025.10.25
代码咕到现在了。发现以前嘴的实现不如这种更直观好写:
节点上记录
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define F(i,l,r) for(int i=l;i<=r;i++)
#define F_(i,r,l) for(int i=r;i>=l;i--)
#define ull unsigned long long
#define pb push_back
#define pii pair<int,int>
#define mp make_pair
#define fi first
#define se second
#define mid ((l+r)>>1)
#define SZ(a) ((int)(a).size())
#define pc putchar
const int mod = 998244353;
const int INF = 1e18;
const int N = 4e5 + 5;
void cmx(int&a,int b){
a=max(a,b);
}
void cmn(int&a,int b){
a=min(a,b);
}
void add(int&a,int b){
a+=b;
if(a>=mod)a-=mod;
}
int rd(){
int x=0,y=1;
char c=getchar();
for(;c<'0'||c>'9';c=getchar())
if(c=='-')y=-1;
for(;c>='0'&&c<='9';c=getchar())
x=(x<<1)+(x<<3)+(c^48);
return x*y;
}
int n,q,a[N];
struct node{
int l1,l2,r1,r2,p,pp,l,r;
bool fl,fl1;
friend node operator+(const node &a,const node &b){
node c;
if(a.r-a.l==0){
c=(node){a.l1,b.l1,b.l1,a.l1,INF,INF,a.l,b.l,0,0};
}else{
if(b.r-b.l==0){
c.l1=a.l1,c.l2=a.l2;
c.r1=b.r1,c.r2=a.r1;
}else{
c.l1=a.l1,c.l2=a.l2;
c.r1=b.r1,c.r2=b.r2;
}
c.l=a.l,c.r=b.r;
if(a.p!=INF){
c.p=a.p;
}else if(a.r2==1&&a.r1==1&&b.l1==0){
c.p=b.l;
}else if(a.r1==1&&b.l1==1&&b.l2==0){
c.p=b.l+1;
}else c.p=b.p;
c.fl=a.fl|b.fl;
if(a.r2==1&&a.r1==0&&b.l1==1||a.r1==1&&b.l1==0&&b.l2==1)
c.fl=1;
if(a.pp!=INF){
c.pp=a.pp;
}else if(a.r2==0&&a.r1==0&&b.l1==1){
c.pp=b.l;
}else if(a.r1==0&&b.l1==0&&b.l2==1){
c.pp=b.l+1;
}else c.pp=b.pp;
c.fl1=a.fl1|b.fl1;
if(a.r2==0&&a.r1==1&&b.l1==0||a.r1==0&&b.l1==1&&b.l2==0)
c.fl1=1;
}
return c;
}
};
struct SGT{
#define ls (rt<<1)
#define rs (rt<<1|1)
node tr[N<<2];
int tg[N<<2];
void apl(int rt){
tr[rt].l1^=1;
tr[rt].l2^=1;
tr[rt].r1^=1;
tr[rt].r2^=1;
swap(tr[rt].p,tr[rt].pp);
swap(tr[rt].fl,tr[rt].fl1);
}
void pu(int rt){
tr[rt]=tr[ls]+tr[rs];
}
void pd(int rt){
if(tg[rt]){
apl(ls),apl(rs);
tg[ls]^=1,tg[rs]^=1;
tg[rt]=0;
}
}
void bd(int l,int r,int rt){
tg[rt]=0;
if(l==r){
int x=a[l];
tr[rt]=(node){x,INF,x,INF,INF,INF,l,r,0,0};
return;
}
bd(l,mid,ls);
bd(mid+1,r,rs);
pu(rt);
// cerr<<l<<' '<<r<<' '<<tr[rt].l1<<' '<<tr[rt].l2<<' '<<tr[rt].r1<<' '<<tr[rt].r2<<' '<<tr[rt].p<<'\n';
}
void upd(int l,int r,int rt,int ql,int qr){
if(ql<=l&&r<=qr){
apl(rt),tg[rt]^=1;
return;
}
pd(rt);
if(ql<=mid)
upd(l,mid,ls,ql,qr);
if(mid+1<=qr)
upd(mid+1,r,rs,ql,qr);
pu(rt);
}
}T;
string s;
int ans;
void get(int x){
// cerr<<x<<'!'<<'\n';
if(T.tr[1].p!=INF){
// cerr<<n-T.tr[1].p+1<<'\n';
ans^=(n-T.tr[1].p+1)*(x+1);
}else if(T.tr[1].fl){
// cerr<<1<<'\n';
ans^=x+1;
}
}
void SOLVE(){
n=rd(),q=rd();
ans=0;
cin>>s;
F(i,1,n){
a[i]=s[i-1]-'0';
}
T.bd(1,n,1);
get(0);
F(i,1,q){
int l=rd(),r=rd();
T.upd(1,n,1,l,r);
get(i);
}
printf("%lld\n",ans);
return;
}
signed main(){
// freopen("a.in","r",stdin);
// freopen("a.out","w",stdout);
int c=rd(),T=rd();
while(T--)SOLVE();
return 0;
}
广告