F---小红不想做模拟题,非线段树,暴力,考虑并查集的方法优化

思路 首先,我们在存好str后手玩一下发现,我们每次查询,需要的是l,r区间中的,字符为0的下标,得到这个下标之后用它去和另一个字符串匹配,如果对应下标的字符是1,那么考虑对ans的贡献加一。 那么问题就成为了如何快速的求得区间中为0的idx下标呢?(一眼线段树,但是调了1h到结束也没调出来555) 考虑开一个下标数组,如果当前下标对应的字符是0,那么这个下标数组对应的val就是自己,否则这个val是下一个字符为0的下标位置。 好的,代码如下

/*
*/
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define int ll
typedef  pair<int,int> pi ;
#define if1(x) for(int i =1 ;i<=x;i++)
#define if0(x) for(int i = 0;i<x;i++)
#define jf0(x) for(int j = 0;j<x;j++)
#define jf1(x) for(int j = 1;j<=x;j++)
const int N = 1e5+10;
int w[N];
int nextw[N];
int ww[N];
int nextww[N];
int ans;
int fd(int u){
    if(nextw[u]==u)return u;
    else return nextw[u] = fd(nextw[u]);
}int fdd(int u){
    if(nextww[u]==u)return u;
    else return nextww[u] = fdd(nextww[u]);
}
void solve(){
    int n,k,m;
    cin>>n;
    string s;
    cin>>s;
    if1(n) w[i] = s[i-1]-'0';
    cin>>s;
    if1(n) ww[i] = s[i-1]-'0';
    if1(n){
        if(w[i]==1&&ww[i]==1)ans++;
    }
    nextw[n+1] = nextww[n+1] = n+1;
    //预处理,把大于等于当前位置的最前面的一个0的位置存下来
   for(int i =n;i>0;i--){
        if(w[i]==0)nextw[i] = i;
        else nextw[i] = nextw[i+1];
        if(ww[i]==0)nextww[i]= i;
        else nextww[i] = nextww[i+1];
   }
    cin>>m;
    while(m--){
        char c;int a,b;
        cin>>c>>a>>b;
        if(c=='A'){
            //大于等于左边界的第一个0,和下一个0
            for(int i = nextw[a];i<=b;i = nextw[i+1]){
                //next 等于自己的是0,否则为oth
                if(nextw[i]!=i){
                    i = fd(i);
                    if(i>b)break;
                }
                if(ww[i]==1)ans++;
                w[i] = 1;
                nextw[i] = nextw[b+1];
                //遍历区间的所有0,并且将他们的下一个0放到区间外面取
                
            }
        }else{
            for(int i = nextww[a];i<=b;i = nextww[i+1]){
                if(nextww[i]!=i){
                    i = fdd(i);
                    if(i>b)break;
                }
                if(w[i]==1)ans++;
                ww[i] = 1;
                nextww[i] = nextww[b+1];
                //遍历区间的所有0,并且将他们的下一个0放到区间外面取
                
            }
        }
        cout<<ans<<endl;
    }
}
signed main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr); 
    int t=1;
    //cin>>t;
    while (t--)
    {
        solve();
    }
    
    return 0;
}