AT3673 [ARC085D] NRE 题解
Problem
给定一个全为(0)的数组(A),给一个数组(B)和(m)个操作,每个操作将数组(A)指定区间改成(1),问合理选择部分操作后使得两个数组的(sum[A_i eq B_i])最小。
Solution
考虑把这个式子变形一下:
[sum[A_i
eq B_i]
\
ightarrow sum[A_i=0][B_i=1]+sum[A_i=1][B_i=0]
\
ightarrow sum[A_i=0]+sum[B_i=0]([A_i=1]-[A_i=0])
]
第一项([A_i=0])是个定值,(([A_i=1]-[A_i=0]))也只和(A)有关,所以现在要考虑的只有([B_i=0])。
考虑DP,设(f_i)表示前(i)个中上式的最小值。首先可以从(f_i)转移到(f_{i+1}),表示不选以(i)为左端点的区间,要么可以转移到右端点
Code
#include<bits/stdc++.h>
using namespace std;
vector<int>L[200005];
int n,m,Ans;
int A[200005];
struct Segment_Tree{
#define ls k<<1|0
#define rs k<<1|1
#define inf 0x3f3f3f3f
int tag[800005],Min[800005];
inline void Pushup(int k){
Min[k]=min(Min[ls],Min[rs]);
}
inline void Pushdown(int k){
if(tag[k]){
tag[ls]+=tag[k];
tag[rs]+=tag[k];
Min[ls]+=tag[k];
Min[rs]+=tag[k];
tag[k];
}
return;
}
void Initialize(){
memset(Min,0x3f,sizeof Min);
}
void Insert(int k,int l,int r,int pos,int val){
if(l==r){
Min[k]=min(Min[k],val);
return;
}
Pushdown(k);
int mid=l+r>>1;
if(pos<=mid)
Insert(ls,l,mid+0,pos,val);
else
Insert(rs,mid+1,r,pos,val);
return Pushup(k);
}
void Change(int k,int l,int r,int wl,int wr,int val){
if(wl> r||l> wr)
return;
if(wl<=l&&r<=wr){
tag[k]+=val;
Min[k]+=val;
return;
}
Pushdown(k);
int mid=l+r>>1;
Change(ls,l,mid+0,wl,wr,val);
Change(rs,mid+1,r,wl,wr,val);
return Pushup(k);
}
int query(int k,int l,int r,int wl,int wr){
if(wl> l||l> wr)
return inf;
if(wl<=l&&r<=wr)
return Min[k];
Pushdown(k);
int res=inf,mid=l+r>>1;
res=min(res,query(ls,l,mid+0,wl,wr));
res=min(res,query(rs,mid+1,r,wl,wr));
return res;
}
#undef ls
#undef rs
#undef inf
}T;
inline int read(){
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){
if(ch=='-')f=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9'){
x=(x<<1)+(x<<3)+ch-'0';
ch=getchar();
}
return x*f;
}
int main(){
n=read();
for(register int i=1;i<=n;++i)
A[i]=read();
m=read();
for(register int i=1;i<=m;++i){
int l=read();
int r=read();
L[l].push_back(r);
}
T.Initialize();
T.Insert(1,0,n,0,0);
for(register int i=1;i<=n;++i){
int N=L[i].size();
for(register int k=0;k<N;++k){
int Min=T.query(1,0,n,0,L[i][k]);
T.Insert(1,0,n,L[i][k],Min);
}
T.Change(1,0,n,0,i-1,A[i]?+1:-1);
Ans+=(A[i]==0);
}
printf("%d
",Ans+T.query(1,0,n,0,n));
return 0;
}