前言
主要是一種暴力思想。。。
本文來自 wiki
與洛谷題解的整合。
應用
主要是應付隨機資料(區間操作)
實現
有幾個核心操作。
set實現方法
定義
struct node
{
intt l,r;//intt:long long
mutable intt v;
node(const intt &ll,const intt &rr,const intt &vv) : l(ll),r(rr),v(vv) {}
bool operator <(const node &o)const
{
return l<o.l;
}
};
set<node>odt;
split 操作(分裂)
auto split(int x)
{
auto it=odt.lower_bound(node(x,0,0));
if(it!=odt.end()&&it->l==x)return it;
it--;
intt l=it->l,r=it->r,v=it->v;
odt.insert(node(l,x-1,v));
return odt.insert(node(x,r,v)).first;
}
- 如果分裂的點恰好是某個區間的左端點,就不用分裂,保留即可。
- 如果分裂的點在一個區間的中間節點,就將其分為 \([l,x-1]\) 和 \([x,r]\) 這兩個區間
- 注意:
odt.insert(node(x,r,v)).first
這表示新加入的node
的位置的迭代器(這是因為insert
返回了一個pair
,first
就只新加入的node
的位置的迭代器了)
assign 操作(區間推平)
void assign(intt l,intt r,intt v)//intt:long long
{
auto itr=split(r+1),itl=split(l);
odt.erase(itl,itr);
odt.insert(node(l,r,v));
}
將邊角餘料分裂出來,再將中間所有元素刪除,最後加入推平區間。
如下圖:
set
的一個用法:erase(first,last)
刪除迭代器在 \([first,last)\) 範圍內所有元素。
add 操作(區間加)
找到每一個段,暴力修改
void add(intt l,intt r,intt v)
{
auto itr=split(r+1),itl=split(l);
for(auto it=itl;it!=itr;it++)
{
it->v+=v;
}
}