珂朵莉树
珂朵莉树
珂朵莉树是暴力解决区间问题的一种优化方式,但本质上依旧是暴力,且在数据随机性很大的时候才会有较高的得分。
虽然珂朵莉树名字中有树,但其实只是区间的拆分合并,跟树没有关系。
比如一开始有区间\([1,25]\),现在更改\([5,17]\),那就把\([1,25]\)拆成\([1,4],[5,17],[18,25]\)。现在再更改\([8,25]\),那就把\([5,17]\)拆成\([5,7]\)和\([8,17]\),再将\([8,17]\)和\([18,25]\)合并,变成\([8,25]\),于是现在就有区间\([1,4],[5,7],[8,25]\)。
然后用\(set\)或者平衡树或者别的方法维护就好了。
这里给出用\(set\)维护的代码。
注意,要先\(split(r+1)\)再\(split(l)\)。
\(s.insert(x).first\)指插入这个数后这个数在的地址
\(s.insert(x).second\)指是否成功插入这个数,成功插入即原集合无\(x\)
#include<bits/stdc++.h>
using namespace std;
#define S_it set<node>::iterator
#define v(it) it->v
#define l(it) it->l
#define r(it) it->r
int n,q,ans;
struct node
{
int l,r;
mutable bool v;
node(int L,int R=-1,bool V=0){l=L;r=R;v=V;}
friend bool operator<(node a,node b)
{
return a.l<b.l;
}
};
set<node>S;
S_it split(int pos)
{
S_it it=S.lower_bound(node(pos));
if(it!=S.end()&&l(it)==pos) return it;
it--;
int l=l(it),r=r(it),v=v(it);
S.erase(it);
S.insert(node(l,pos-1,v));
return S.insert(node(pos,r,v)).first;
}
void put(int l,int r,int k)
{
S_it itr=split(r+1);
S_it itl=split(l);
for(S_it it=itl;it!=itr;it++) ans-=v(it)*(r(it)-l(it)+1);
S.erase(itl,itr);
S.insert(node(l,r,k));
ans+=k*(r-l+1);
}
int main()
{
scanf("%d %d",&n,&q);
ans=n;
S.insert(node(1,n,1));
for(int i=1,l,r,k;i<=q;++i)
{
scanf("%d %d %d",&l,&r,&k);
put(l,r,k-1);
printf("%d\n",ans);
}
return 0;
}

浙公网安备 33010602011771号