do_while_true

一言(ヒトコト)

「题解」Codeforces 1638E Colorful Operations

每次区间染色,会删除若干个颜色段,添加 \(\mathcal{O}(1)\) 个颜色段。因此颜色段总数是 \(\mathcal{O}(n+q)\)

采用平衡树(用 set 即可)维护极长连续颜色段,维护每个颜色增加值大小的 \(tag\),并用树状数组维护每个点的答案减去对应颜色的 \(tag\) 值。

Add:直接给对应颜色的 \(tag\) 进行修改。

Color:当删除一个颜色段时,就将其区间加上原先颜色的 \(tag\) 值;当添加一个颜色段时,就将其区间减去新颜色的 \(tag\) 值(因为新颜色原先的 \(tag\) 并没有加在这一段上,需要减去)。

Query:输出答案即可,即树状数组维护的值加上对应颜色的 \(tag\) 值。

不难发现树状数组操作次数和颜色段次数呈线性,时间复杂度 \(\mathcal{O}((n+q)\log n)\)

#include<cstdio>
#include<vector>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<set>
#define pb emplace_back
#define mp std::make_pair
#define fi first
#define se second
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef std::pair<int,int>pii;
typedef std::pair<ll,int>pli;
typedef std::pair<ll,ll>pll;
typedef std::vector<int>vi;
typedef std::vector<ll>vll;
template<typename T>T cmax(T &x, T y){return x=x>y?x:y;}
template<typename T>T cmin(T &x, T y){return x=x<y?x:y;}
template<typename T>
T &read(T &r){
	r=0;bool w=0;char ch=getchar();
	while(ch<'0'||ch>'9')w=ch=='-'?1:0,ch=getchar();
	while(ch>='0'&&ch<='9')r=r*10+(ch^48),ch=getchar();
	return r=w?-r:r;
}
template<typename T1,typename... T2>
void read(T1 &x, T2& ...y){ read(x); read(y...); }
const int N=1000010;
inline int lowbit(int x){return x&(-x);}
int n,q;
ll tree[N],tag[N];
void modify(int x,ll v){
	for(;x<=n;x+=lowbit(x))tree[x]+=v;
}
void change(int x,int y,ll v){
	modify(x,v);
	if(y<n)modify(y+1,-v);
}
ll query(int x){
	ll s=0;
	for(;x;x-=lowbit(x))s+=tree[x];
	return s;
}
struct Node{
	int l,r,c;
	Node(int x=0,int y=0,int z=0){
		l=x;r=y;c=z;
	}
	bool operator < (const Node &x)const{
		return l<x.l;
	}
};
set<Node>st;
#define IT set<Node>::iterator
IT split(int pos){
	auto it=st.lower_bound(Node(pos,pos,0));
	if(it!=st.end()&&(*it).l==pos)return it;
	--it;
	int L=(*it).l,R=(*it).r,C=(*it).c;
	st.erase(it);
	st.insert(Node(L,pos-1,C));
	return st.insert(Node(pos,R,C)).first;
}
void assign(int l,int r,int c){
	auto itr=split(r+1),itl=split(l);
	auto it=split(l);
	for(;it!=itr;++it)
		change((*it).l,(*it).r,tag[(*it).c]);
	st.erase(itl,itr);
	st.insert(Node(l,r,c));
	change(l,r,-tag[c]);
}
int Col(int l,int r){
	auto it=st.lower_bound(Node(l,r,0));
	while(it==st.end()||(!(l>=(*it).l && r<=(*it).r)))--it;
	return (*it).c;
}
signed main(){
	#ifdef do_while_true
	freopen("data.in","r",stdin);
	#endif 
	read(n,q);
	st.insert(Node(1,n,1));
	while(q--){
		char ch=getchar();while(ch!='C'&&ch!='A'&&ch!='Q')ch=getchar();
		if(ch=='A'){
			int c,x;read(c,x);
			tag[c]+=x;
		}
		else if(ch=='Q'){
			int x;read(x);
			cout << query(x)+tag[Col(x,x)] << '\n';
		}
		else{
			int l,r,c;read(l,r,c);
			assign(l,r,c);
		}
	}
	return 0;
}
posted @ 2022-02-16 15:09  do_while_true  阅读(144)  评论(0编辑  收藏  举报