考虑每种颜色的贡献,用总数 \(n-k+1\) 减去没有贡献到的(极长连续段长度为 \(len\) 时),贡献为 \(\max(len-k+1,0)\),所以考虑用 \(\text{ODT}\) 维护所有颜色的连续段。
具体的,维护一个大的 \(ODT\) 存储所有连续段,再对每个颜色存储自己的连续段,用 \(\text{BIT}\) 维护每个长度的极长连续段的长度总和以及出现次数。
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<vector>
#include<set>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N=2e5+5;
struct node{
ll l;ll r;ll c;
inline bool operator < (const node &t)const{
return l<t.l;
}
};
ll n,q,a[N],o[N],cnto;
ll opt[N],el[N],er[N],ex[N];
set<node> S[N];ll cs[N];ll kind;
inline void read(ll &x)
{
ll f=1;char c;
for(x=0,c=getchar();c<'0'||c>'9';c=getchar()) if(c=='-') f=-1;
for(;c>='0'&&c<='9';c=getchar()) x=(x<<1)+(x<<3)+(c^48); x*=f;
}
inline ll mn(ll _x,ll _y){return _x<_y?_x:_y;}
inline ll mx(ll _x,ll _y){return _x>_y?_x:_y;}
inline ll ab(ll _x){return _x<0?-_x:_x;}
ll sum[N],cnt[N];
inline ll lowbit(ll x){return x&-x;}
inline void update(ll x,ll o){
ll v=x;++x;
while(x<=n+1){sum[x]+=1ll*o*v;cnt[x]+=o;x+=lowbit(x);}
return ;
}
inline ll qc(ll x){
++x;ll res=0;
while(x){res+=cnt[x];x-=lowbit(x);}
return res;
}
inline ll qs(ll x){
++x;ll res=0;
while(x){res+=sum[x];x-=lowbit(x);}
return res;
}
inline ll Qc(ll l,ll r){
ll res=qc(r);
if(l) res-=qc(l-1);
return res;
}
inline ll Qs(ll l,ll r){
ll res=qs(r);
if(l) res-=qs(l-1);
return res;
}
inline void SegIns(ll l,ll r,ll c){
set<node>::iterator ita=S[c].lower_bound((node){l,r,c});
set<node>::iterator itb;itb=ita;--itb;
update(ita->l-itb->r-1,-1);
set<node>::iterator it=S[c].insert((node){l,r,c}).first;
update(it->l-itb->r-1,1);
update(ita->l-it->r-1,1);
return ;
}
inline void SegDel(ll l,ll r,ll c){
set<node>::iterator it=S[c].find((node){l,r,c});
set<node>::iterator ita,itb;ita=it;--ita;itb=it;++itb;
update(it->l-ita->r-1,-1);
update(itb->l-it->r-1,-1);
update(itb->l-ita->r-1,1);
S[c].erase(it);return ;
}
inline set<node>::iterator split(ll pos){
set<node>::iterator it=S[0].lower_bound((node){pos,pos,0});
if(it!=S[0].end()&&it->l==pos) return it;
--it;
ll _l=it->l,_r=it->r,_c=it->c;
S[0].erase(it);
S[_c].erase((node){_l,_r,_c});
if(_l<pos) {
S[0].insert((node){_l,pos-1,_c});
S[_c].insert((node){_l,pos-1,_c});
}
S[_c].insert((node){pos,_r,_c});
return S[0].insert((node){pos,_r,_c}).first;
}
inline void Assign(ll l,ll r,ll v){
set<node>::iterator itr=split(r+1),itl=split(l);
for(set<node>::iterator it=itl;it!=itr;++it){
SegDel(it->l,it->r,it->c);
}
S[0].erase(itl,itr);
S[0].insert((node){l,r,v});
SegIns(l,r,v);
return ;
}
inline ll Qk(ll k){
ll res=0;
res+=Qs(k,n);
res-=Qc(k,n)*(k-1);
return 1ll*cnto*(n-k+1)-res;
}
int main()
{
read(n);read(q);
for(ll i=1;i<=n;i++){
read(a[i]);o[++cnto]=a[i];
}
for(ll i=1;i<=q;i++){
read(opt[i]);
if(opt[i]==1){
read(el[i]);read(er[i]);read(ex[i]);
o[++cnto]=ex[i];
}
else read(ex[i]);
}
sort(o+1,o+cnto+1);
cnto=unique(o+1,o+cnto+1)-o-1;
for(ll i=1;i<=n;i++)
a[i]=lower_bound(o+1,o+cnto+1,a[i])-o;
for(ll i=1;i<=q;i++)
if(opt[i]==1) ex[i]=lower_bound(o+1,o+cnto+1,ex[i])-o;
for(ll i=1;i<=cnto;i++){
S[i].insert((node){n+1,n+1,i});
S[i].insert((node){0,0,i});
update(n,1);
}
S[0].insert((node){0,0,0});
S[0].insert((node){n+1,n+1,0});
for(ll i=1;i<=n;i++) {
SegIns(i,i,a[i]);
S[0].insert((node){i,i,a[i]});
}
for(ll i=1;i<=q;i++){
if(opt[i]==1) Assign(el[i],er[i],ex[i]);
else printf("%lld\n",Qk(ex[i]));
}
return 0;
}
标签:node,set,iterator,题解,ll,itb,ita,Growing,flowers
From: https://www.cnblogs.com/ReineRabbit/p/17895829.html