题目链接:https://codeforces.com/contest/1847/problem/D
思路:对于同一个位置,后出现的是无意义的,所以只需要找到每个位置第一次出现的次序,暴力写是的,可以转化为区间覆盖模型,这是并查集的一个经典应用。对于询问,先统计原字符串中1的个数cnt,最小操作数ans。然后对于每个询问动态维护cnt,ans,s的值即可。
注意:并查集初始话一定要到p[n+1],不然在导致MLE
Code
//并查集
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<vector>
#include<queue>
#include<map>
#include<set>
using namespace std;
#define PII pair<int,int>
#define endl "\n"
typedef long long LL;
const int N=2e5+10;
int p[N];
int pos[N];
int find(int x) {if(p[x]!=x) p[x]=find(p[x]);return p[x];
}
void solve() {int n,m,q;string s;cin>>n>>m>>q>>s;s='?'+s;for(int i=1;i<=n+1;i++) p[i]=i,pos[i]=-1; //p[n+1]也要初始化vector<int> v;int _idx=0;while(m--) {int l,r;cin>>l>>r;for(int i=find(l);i<=r;i=find(i)) {v.push_back(i); pos[i]=++_idx;p[i]=i+1;}}int cnt=0;for(int i=1;i<=n;i++) {cnt+=(s[i]=='1');}int ans=0;for(int i=0;i<min(cnt,(int)v.size());i++) {ans+=(s[v[i]]=='0');}while(q--) {int idx;cin>>idx;if(pos[idx]!=-1&&pos[idx]<=cnt) {if(s[idx]=='0') ans--;else ans++;}if(s[idx]=='0') {s[idx]='1';cnt++;if(cnt<=(int)v.size()&&s[v[cnt-1]]=='0') ans++;}else {s[idx]='0';if(cnt<=(int)v.size()&&s[v[cnt-1]]=='0') ans--;cnt--;}cout<<ans<<endl;}
}
int main() {ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr);solve();return 0;
}
这里我vector越界了,然后TLE了,奇怪的TLE原因增加了