首先给出一串字符串观察一下:
001010111
假设当L=2,R=7时 那么最后排序的情况是:000011111
假设当L=1,R=8时 可以发现最后的排序情况跟上面一种情况是一样的
更直观点来看:
000000011111111
当L处于左边0的任何位置,R处于右边1的任何位置,那么最终的结果不会发生变化
因此可以记录一下每个0右边第一个1的位置,同时记录每个1左边第一个0的位置,那么只需修改中间值即可。如图:
对于左边任何区间来说,不管L在哪最后结果都是一样,修改的是红色区间,右边也一样。
最后用map哈希表记录即可。
代码附上:
#include <bits/stdc++.h>
#define int long long
#define first x
#define second y
using namespace std;
const int N =2e5+5;
int l[N],r[N];
int n,m;
int a[N];
void solve(){
map<pair<int,int>,int>mp;
cin>>n>>m;
string s;cin>>s;
for(int i=1;i<=n;i++){
a[i]=s[i-1]-'0';
}
int pos=0;
for(int i=1;i<=n;i++){//每个1左边第一个0的位置
if(a[i]==0)pos=i;
l[i]=pos;
}
pos=n+1;
for(int i=n;i>=1;i--){//每个0右边第一个1的位置
if(a[i]==1)pos=i;
r[i]=pos;
}
int ans=0;
for(int i=1;i<=m;i++){
int x,y;cin>>x>>y;
x=r[x];
y=l[y];
if(x>y)x=1,y=1;//跟原来字符串一样,不变
if(!mp[{x,y}]){
mp[{x,y}]=1;
ans++;
}
}
cout<<ans<<"\n";
return;
}
signed main(){
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
int t;cin>>t;
while(t--){
solve();
}
return 0;
}