题解:P8441 旭日东升
感觉大家写的 ODT 都太冗长了,提供一种不用大量分讨的写法,思路请去别的题解查看。
首先先插入区间
我们希望能直接找到所有需要删去的区间
注意到即条件
可以用 upper_bound 找到第一个左端点大于
用 lower_bound 找到第一个左端点大于等于
很容易得到要插入区间的真实左右端点。
删去
struct ODT{
set<array<int,2>> odt;
ODT(){odt.insert({-1,-1});}
void assign(int l,int r,int v){
auto itl=odt.lower_bound({l,0}),itr=odt.upper_bound({r+1,0});
if(l-1<=(*prev(itl))[1])itl=prev(itl);
int L=min(l,itl!=odt.end()?(*itl)[0]:INF),R=max(r,(*prev(itr))[1]);
for(auto it=itl;it!=itr;++it)CDQ.addu((*prev(it))[1],(*it)[0],(*it)[1],-v);
if(itr!=odt.end())CDQ.addu((*prev(itr))[1],(*itr)[0],(*itr)[1],-v),CDQ.addu(R,(*itr)[0],(*itr)[1],v);
odt.erase(itl,itr);CDQ.addu((*prev(odt.insert({L,R}).first))[1],L,R,v);
}
}ODT[N];