题解:AT_abc470_g [ABC470G] ΣШX
我们充分发挥联想能力:
做过 P13780 和 P9970 的应该都知道:定义一个区间
我们明显有
考虑这么一个做法:
- 对于长度为
1 的区间,如果为0 则为\textup{mex} 为1 的极小\textup{mex} 区间,否则为\textup{mex} 为0 的极小\textup{mex} 区间。 - 遍历所有
x :- 遍历
\textup{mex} 为x-1 的所有极小\textup{mex} 区间,找到距离左端点最近且在其左边的x ,以及距离右端点最近且在其右边的x ,扩展区间到该位置,并将其记录为对应\textup{mex} 的\textup{mex} 区间。 - 对
\textup{mex} 为x 的区间求极小。
- 遍历
这里需要用到在线
又有显然的结论:一个区间的
于是考虑扫描线,把所有的极小
复杂度
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define ui unsigned int
#define fi first
#define se second
#define pii pair<int,int>
#define lowbit(x) ((x)&(-(x)))
#define popc(x) __builtin_popcountll(x)
#define ctz(x) __builtin_ctzll(x)
#define clz(x) __builtin_clzll(x)
#define double long double
#define sqrt(x) sqrtl(x)
#define cbrt(x) cbrtl(x)
#define pow(x,y) powl(x,y)
#define sin(x) sinl(x)
#define cos(x) cosl(x)
#define tan(x) tanl(x)
#define pb emplace_back
const int N=3e5+10,mod=998244353;
int a[N],n,q;
vector<int>vec[N];
vector<pii>g[N];
int pre(vector<int>& v,int x)
{
auto p=upper_bound(v.begin(),v.end(),x);
if(p!=v.begin()) return *(--p);
return -1;
}
int nxt(vector<int>& v,int x)
{
auto p=lower_bound(v.begin(),v.end(),x);
if(p!=v.end()) return *p;
return -1;
}
struct persgt
{
struct node
{
int ls,rs;
int sum;
}tr[N<<5];
int rt[N],tot;
int& operator[](int x){return rt[x];}
int copy(int u)
{
tr[++tot]=tr[u];
return tot;
}
void pushup(int u)
{
tr[u].sum=min(tr[tr[u].ls].sum,tr[tr[u].rs].sum);
}
void modify(int& u,int v,int l,int r,int p,int x)
{
u=copy(v);
if(l==r)
{
tr[u].sum=x;
return;
}
int mid=l+r>>1;
if(p<=mid) modify(tr[u].ls,tr[v].ls,l,mid,p,x);
else modify(tr[u].rs,tr[v].rs,mid+1,r,p,x);
pushup(u);
}
int query(int u,int l,int r,int x)
{
if(l==r) return l;
int mid=l+r>>1;
if(tr[tr[u].ls].sum<x) return query(tr[u].ls,l,mid,x);
else return query(tr[u].rs,mid+1,r,x);
}
}tr;
struct sgt
{
struct node
{
int sum,mn,tag;
}tr[N<<2];
void pushup(int u)
{
tr[u].sum=tr[u*2].sum+tr[u*2+1].sum;
tr[u].mn=min(tr[u*2].mn,tr[u*2+1].mn);
}
void pd(int u,int l,int r)
{
if(tr[u].tag==0) return;
int mid=l+r>>1;
tr[u*2].tag=tr[u*2].mn=tr[u].tag;
tr[u*2].sum=(mid-l+1)*tr[u].tag;
tr[u*2+1].tag=tr[u*2+1].mn=tr[u].tag;
tr[u*2+1].sum=(r-mid)*tr[u].tag;
tr[u].tag=0;
}
int find(int u,int l,int r,int x)
{
if(tr[u].mn>x) return r+1;
if(l==r) return l;
pd(u,l,r);
int mid=l+r>>1;
if(tr[u*2].mn<=x) return find(u*2,l,mid,x);
else return find(u*2+1,mid+1,r,x);
}
void modify(int u,int l,int r,int L,int R,int x)
{
if(L<=l&&r<=R)
{
tr[u].tag=tr[u].mn=x;
tr[u].sum=(r-l+1)*x;
return;
}
pd(u,l,r);
int mid=l+r>>1;
if(L<=mid) modify(u*2,l,mid,L,R,x);
if(R>mid) modify(u*2+1,mid+1,r,L,R,x);
pushup(u);
}
}tr2;
vector<pii>ms[N];
signed main()
{
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>a[i];
vec[a[i]].pb(i);
tr.modify(tr[i],tr[i-1],0,n,a[i],i);
}
for(int i=1;i<=n;i++)
{
if(a[i]) g[0].pb(i,i);
else g[1].pb(i,i);
}
for(int i=1;i<=n;i++)
{
for(auto v:g[i-1])
{
int l=v.fi,r=v.se;
int pl=pre(vec[i-1],l),pr=nxt(vec[i-1],r);
if(pl!=-1) g[tr.query(tr[r],0,n,pl)].pb(pl,r);
if(pr!=-1) g[tr.query(tr[pr],0,n,l)].pb(l,pr);
}
sort(g[i].begin(),g[i].end(),[](pii x,pii y){return x.fi!=y.fi?x.fi>y.fi:x.se<y.se;});
vector<pii>t;
int ls=1e18;
for(auto v:g[i])
{
if(ls>v.se) t.pb(v);
ls=min(ls,v.se);
}
g[i]=move(t);
}
for(int i=1;i<=n;i++) for(auto v:g[i]) ms[v.se].pb(v.fi,i);
int ans=0;
for(int i=1;i<=n;i++)
{
for(auto v:ms[i])
{
int p=tr2.find(1,1,n,v.se);
if(p>v.fi) continue;
tr2.modify(1,1,n,p,v.fi,v.se);
}
ans+=tr2.tr[1].sum;
}
cout<<ans;
return 0;
}
:::