【题解】CF1847D Professor Higashikata
题面传送门
解决思路
首先我们考虑,优先把原字符串 1
会使得拼接后字符串
然后考虑如何求出每个位置的优先级。这里讲一种区间覆盖的方法。从最后一个区间开始做区间覆盖。对于第
再考虑求出优先级后如何计算每次询问的答案。我们假设当前原字符串 有用的 1
的个数为 1
。设原字符串中优先级前 1
。那么答案显而易见,就是
注意上一段的粗体字:什么是有用的 1
?考虑一种情况,那就是原字符串 0
或 1
是无所谓的。所以如果计算全部 1
的个数作为 1
,从而使答案偏大。所以 没有考虑这一点会导致 Wa on 13)
具体实现中,区间覆盖和维护 1
的个数我选用的都是线段树,所以看着比较长,其实是不难写的。
AC Code
//If, one day, I finally manage to make my dreams a reality...
//I wonder, will you still be there by my side?
#include<bits/stdc++.h>
#define IOS ios::sync_with_stdio(false)
#define TIE cin.tie(0),cout.tie(0)
#define int long long
#define y1 cyy
#define fi first
#define se second
#define cnt1(x) __builtin_popcount(x)
#define mk make_pair
#define pb push_back
#define pii pair<int,int>
#define ls(x) (x<<1)
#define rs(x) (x<<1|1)
#define lbt(x) (x&(-x))
using namespace std;
struct SGT{
struct node{
int l,r,sum,tag;
}tr[800005];
void build(int i,int l,int r){
tr[i].l=l,tr[i].r=r,tr[i].tag=0;
if(l==r) return ;
int mid=(l+r)>>1;
build(ls(i),l,mid),build(rs(i),mid+1,r);
tr[i].sum=tr[ls(i)].sum+tr[rs(i)].sum;
}
void pushdown(int i){
if(tr[i].tag){
tr[ls(i)].tag=tr[i].tag;
tr[rs(i)].tag=tr[i].tag;
tr[ls(i)].sum=(tr[ls(i)].r-tr[ls(i)].l+1)*tr[i].tag;
tr[rs(i)].sum=(tr[rs(i)].r-tr[rs(i)].l+1)*tr[i].tag;
tr[i].tag=0;
}
}
void turn(int i,int l,int r,int k){
if(tr[i].l>=l&&tr[i].r<=r){
tr[i].tag=k,tr[i].sum=(tr[i].r-tr[i].l+1)*k;
return ;
}
pushdown(i);
int mid=(tr[i].l+tr[i].r)>>1;
if(l<=mid) turn(ls(i),l,r,k);
if(mid<r) turn(rs(i),l,r,k);
tr[i].sum=tr[ls(i)].sum+tr[rs(i)].sum;
}
int query(int i,int l,int r){
if(tr[i].l>=l&&tr[i].r<=r) return tr[i].sum;
pushdown(i);
int mid=(tr[i].l+tr[i].r)>>1,ans=0;
if(l<=mid) ans+=query(ls(i),l,r);
if(mid<r) ans+=query(rs(i),l,r);
return ans;
}
}sgt;
struct SGT2{
struct node{
int l,r,sum,tag;
}tr[800005];
void build(int i,int l,int r){
tr[i].l=l,tr[i].r=r,tr[i].sum=tr[i].tag=0;
if(l==r){
tr[i].sum=0;
return ;
}
int mid=(l+r)>>1;
build(ls(i),l,mid),build(rs(i),mid+1,r);
tr[i].sum=tr[ls(i)].sum+tr[rs(i)].sum;
}
void pushdown(int i){
if(tr[i].tag){
tr[ls(i)].tag+=tr[i].tag;
tr[rs(i)].tag+=tr[i].tag;
tr[ls(i)].sum+=(tr[ls(i)].r-tr[ls(i)].l+1)*tr[i].tag;
tr[rs(i)].sum+=(tr[rs(i)].r-tr[rs(i)].l+1)*tr[i].tag;
tr[i].tag=0;
}
}
void add(int i,int l,int r,int k){
if(tr[i].l>=l&&tr[i].r<=r){
tr[i].tag+=k,tr[i].sum+=(tr[i].r-tr[i].l+1)*k;
return ;
}
pushdown(i);
int mid=(tr[i].l+tr[i].r)>>1;
if(l<=mid) add(ls(i),l,r,k);
if(mid<r) add(rs(i),l,r,k);
tr[i].sum=tr[ls(i)].sum+tr[rs(i)].sum;
}
int query(int i,int l,int r){
if(tr[i].l>=l&&tr[i].r<=r) return tr[i].sum;
pushdown(i);
int mid=(tr[i].l+tr[i].r)>>1,ans=0;
if(l<=mid) ans+=query(ls(i),l,r);
if(mid<r) ans+=query(rs(i),l,r);
return ans;
}
}sgt2;
struct node{
int l,r;
}a[200005];
struct dot{
int id,rk;
}b[200005];
bool cmp(dot a,dot b){
if(a.rk==b.rk) return a.id<b.id;
return a.rk>b.rk;
}
int T,n,m,q,t;
string s;
int yxj[200005];
void solve(){
cin>>n>>m>>q>>s;
s=" "+s;
for(int i=1;i<=m;i++) cin>>a[i].l>>a[i].r;
int tmp=1;
sgt.build(1,1,n);
for(int i=m;i>=1;i--) sgt.turn(1,a[i].l,a[i].r,tmp++);
for(int i=1;i<=n;i++) b[i]={i,sgt.query(1,i,i)};
sort(b+1,b+n+1,cmp);
int mx=n;
for(int i=1;i<=n;i++){
yxj[b[i].id]=i;
if(b[i].rk==0) mx=min(mx,i-1);
}
int c1=0;
sgt2.build(1,1,n);
for(int i=1;i<=n;i++){
if(s[i]=='1') c1++,sgt2.add(1,yxj[i],yxj[i],1);
}
while(q--){
cin>>t;
if(s[t]=='0'){
s[t]='1';c1++;
sgt2.add(1,yxj[t],yxj[t],1);
}
else{
s[t]='0';c1--;
sgt2.add(1,yxj[t],yxj[t],-1);
}
cout<<min(c1,mx)-sgt2.query(1,1,min(c1,mx))<<endl;
}
}
signed main(){
IOS;TIE;
T=1;
while(T--) solve();
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话