2025 ICPC网络赛第一场 L cover
给一个长度为 \(n\) 的序列 \(\{a_n\}\) 和 \(m\) 个操作,其中第 \(i\) 个操作是把区间 \([l_i,r_i]\) 都赋值为 \(c_i\)。
现在按顺序遍历每个操作,每个操作可执行可不执行。
最大化序列的颜色段数,即 \(1+\sum\limits_{i=2}^n[a_{i-1}\not=a_i]\)。
\(1\leq a_i,c_i\leq n\leq\sum n\leq3\times10^5,1\leq m\leq\sum m\leq3\times10^5\)。
\(\forall 1\leq i<j\leq n,[l_j,r_j]\nsubseteq [l_i,r_i]\)。
首先,设 \(f_n\) 表示只考虑前 \(i\) 项且第 \(i\) 项保留原本值时最大颜色段数。
令 \(a_0=a_{n+1}=0\),答案就是 \(f_{n+1}-1\)。
有转移方程 \(f_{i}=\max\{f_{i-1}+[a_i\not=a_{i-1}],\max\limits_{0\leq j<i-1}\{f_j+\text{maxcolor}(j,i)\}\}\)。
其中 \(\text{maxcolor}(j,i)\) 表示当 \(a_j,a_i\) 都保留原本值时 \([j+1,i]\) 贡献的颜色段数的最大值。
显然 \(\text{maxcolor}(j,i)\) 并不能直接用式子表示。
设 \(g_i\) 表示第 \(i\) 个操作执行且 \(a_{r_i}\) 最终被第 \(i\) 次操作覆盖时 \([1,r_i]\) 的最大颜色段数。
更新我们的转移方程:
\(f_i=\max\{f_{i-1}+[a_i\not=a_{i-1}],\max\limits_{r_j=i-1}\{g_j+[c_j\not=a_i]\}\}\)
\(g_i=\max\{f_{l_i-1}+[c_i\not=a_{l_i-1}],\max\limits_{0\leq j<i,l_j\leq l_i-1\leq r_j\leq r_i}\{g_j+[c_j\not=c_i]\},\max\limits_{i<j\leq m,r_j<r_i}\{g_j+[c_j\not=c_i]\}\}\)
使用线段树优化即可做到 \(O(n+m\log m)\)。
#include<bits/stdc++.h>
using namespace std;
const int MAXN=300005,inf=1e9;
const pair<int,int> Inf=make_pair(-inf,-1);
inline int read() {
static int x=0,c=getchar(),f=1;
for(f=1; c<=47||c>=58; c=getchar())f=f&&(c^45);
for(x=0; c>=48&&c<=57; c=getchar())x=(x<<3)+(x<<1)+(c&15);
return f?x:-x;
}
struct node {
pair<int,int>a,b;
inline node(pair<int,int>A=Inf,pair<int,int>B=Inf) {
a=A,b=B;
}
};
inline node Merge(node x,node y) {
static node z;
z.a=max(x.a,y.a),z.b=Inf;
if(x.a.second!=z.a.second) z.b=x.a;
if(y.a.second!=z.a.second) z.b=max(z.b,y.a);
if(x.b.second!=z.a.second) z.b=max(z.b,x.b);
if(y.b.second!=z.a.second) z.b=max(z.b,y.b);
return z;
}
struct Tree {
node val,tg;
} tr[MAXN<<2];
void build(int num,int l,int r) {
tr[num].val=tr[num].tg=node();
if(l==r)return;
build(num<<1,l,(l+r)>>1),build(num<<1|1,(l+r+2)>>1,r);
}
inline void Tag(int num,node x) {
if(~x.a.second) {
tr[num].tg=Merge(tr[num].tg,x);
static node p;
p=tr[num].val;
if(~p.a.second) {
tr[num].val=Merge(tr[num].val,node(make_pair(x.a.first+(x.a.second!=p.a.second),p.a.second)));
if(~x.b.second)
tr[num].val=Merge(tr[num].val,node(make_pair(x.b.first+(x.b.second!=p.a.second),p.a.second)));
if(~p.b.second) {
tr[num].val=Merge(tr[num].val,node(make_pair(x.a.first+(x.a.second!=p.b.second),p.b.second)));
if(~x.b.second)
tr[num].val=Merge(tr[num].val,node(make_pair(x.b.first+(x.b.second!=p.b.second),p.b.second)));
}
}
}
}
void push_down(int num) {
if(~tr[num].tg.a.second) {
Tag(num<<1,tr[num].tg);
Tag(num<<1|1,tr[num].tg);
tr[num].tg=node();
}
}
void upd(int num,int l,int r,int x,node v) {
if(l==r) {
tr[num].val=v;
return;
}
push_down(num);
int mid=(l+r)>>1;
if(x<=mid)upd(num<<1,l,mid,x,v);
else upd(num<<1|1,mid+1,r,x,v);
tr[num].val=Merge(tr[num<<1].val,tr[num<<1|1].val);
}
void update(int num,int l,int r,int L,int R,node x) {
if(L>R)return;
if(L<=l&&r<=R) return Tag(num,x);
push_down(num);
int mid=(l+r)>>1;
if(L<=mid) update(num<<1,l,mid,L,R,x);
if(mid<R)update(num<<1|1,mid+1,r,L,R,x);
tr[num].val=Merge(tr[num<<1].val,tr[num<<1|1].val);
}
node query(int num,int l,int r,int L,int R) {
if(L>R)return Inf;
if(L<=l&&r<=R)return tr[num].val;
push_down(num);
int mid=(l+r)>>1;
if(R<=mid) return query(num<<1,l,mid,L,R);
if(mid<L)return query(num<<1|1,mid+1,r,L,R);
return Merge(query(num<<1,l,mid,L,mid),query(num<<1|1,mid+1,r,mid+1,R));
}
int n,m,a[MAXN],col[MAXN],f[MAXN];
vector<int>add[MAXN],del[MAXN];
vector<node>vec;
inline void solve() {
n=read(),m=read(),a[n+1]=0;
for(int i=1; i<=n; ++i)a[i]=read();
for(int i=1; i<=m; ++i) {
add[read()].push_back(i);
del[read()+1].push_back(i);
col[i]=read();
}
build(1,1,m);
for(int i=1; i<=n+1; ++i) {
f[i]=f[i-1]+(a[i]!=a[i-1]);
vec.clear();
for(int x:add[i])vec.push_back(query(1,1,m,1,x-1));
for(int x:add[i])upd(1,1,m,x,node(make_pair(-inf,col[x])));
for(unsigned j=0; j<vec.size(); ++j)
update(1,1,m,add[i][j],add[i][j],Merge(node(make_pair(f[i-1],a[i-1])),vec[j]));
vec.clear();
for(int x:del[i]) {
vec.push_back(query(1,1,m,x,x));
f[i]=max(f[i],vec.back().a.first+(col[x]!=a[i]));
upd(1,1,m,x,node());
}
for(unsigned j=0; j<vec.size(); ++j)
update(1,1,m,1,del[i][j],node(vec[j].a));
add[i].clear(),add[i].shrink_to_fit();
del[i].clear(),del[i].shrink_to_fit();
}
printf("%d\n",f[n+1]-1);
}
int main() {
int t=read();
while(t--)solve();
return 0;
}

浙公网安备 33010602011771号