1 条题解
-
0
对于操作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; }
- 1
信息
- ID
- 202
- 时间
- 1500ms
- 内存
- 256MiB
- 难度
- 8
- 标签
- 递交数
- 33
- 已通过
- 5
- 上传者