1 条题解

  • 0
    @ 2026-5-11 20:12:42

    对于操作1来说,由于找到了1,就会把1改为0,我们可以断言,对于操作1来说,所有1的贡献不超过1

    对于操作2来说,虽然不会改变数组的值,但是一次最多访问一个元素,因此,也不会访问超过Q次

    如果暴力实现操作1,注意到很多位置的遍历是重复的,我们需要一个能快速找到下一个1的位置的数据结构

    这是并查集的经典用法(维护下一个可选位置),如果你不知道怎么实现一个并查集,请看下面的AC代码,给出了并查集的一种较为简洁的实现

    #include<bits/stdc++.h>
    using namespace std;
    using u64 = unsigned long long;
    struct dsu
    {
        vector<int>fa;
        dsu(int n){
            fa.resize(n);
            for(int i = 0;i<n;i++) fa[i] = i;
        }
        int find(int x) {return x==fa[x]?x:fa[x] = find(fa[x]);}
        void unite(int x,int y){fa[find(x)] = find(y);}
    };
    int main()
    {
        ios::sync_with_stdio(0);
        cin.tie(0);
        cout.tie(0);
        int n,q;
        cin>>n>>q;
        string s;
        cin>>s;
        //维护下一个1的位置
        dsu nxt1(n+2);
        for(int i = 1;i<=n;i++){
            if(s[i-1]=='0') nxt1.unite(i,i+1);
        }
        u64 ansSum = 0;
        u64 ansXor = 0;
        while(q--){
            int opt ;
            cin>>opt;
            if(opt==1){
                int l ,r;
                cin>>l>>r;
                int curr = nxt1.find(l);
                int cnt = 0;
                while(curr<=r){
                    cnt++;
                    nxt1.unite(curr,curr+1);
                    curr = nxt1.find(curr+1);
                }
                ansSum += u64(cnt);
                ansXor ^= u64(cnt);
            }
            else{
                int k;
                cin>>k;
                auto ret = nxt1.find(k+1);
                if(ret==n+1) ret = -1;
                ansSum += u64(ret);
                ansXor ^= u64(ret);
            }
        }
        cout<<ansSum<<" "<<ansXor<<endl;
    }
    

    信息

    ID
    202
    时间
    1500ms
    内存
    256MiB
    难度
    8
    标签
    递交数
    33
    已通过
    5
    上传者