CF1423G Growing flowers题解

考虑每种颜色的贡献,用总数 \(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;
}
posted @ 2024-01-28 11:33  ReineRabbit  阅读(28)  评论(0)    收藏  举报