注释很详细了
代码基本上都是对着kuangbin的抄的
#include <iostream>
#include <cstring>
///给出每一段的颜色 后面加入的覆盖前面的 求每种颜色有几个线段
///区间更新每一段的值 那么线段树中储存的是每一段的值
using namespace std;
const int N=8010;
inline int lson(int t){return t<<1;}
inline int rson(int t){return lson(t)|1;}
struct Node{
int l,r,color;
Node(int _l,int _r,int _c){l=_l;r=_r;color=_c;}
Node(){}
}segTree[N<<2];
void built(int t,int l,int r)
{
segTree[t]=Node(l,r,-1);
if(l==r)return;
int mid=(l+r)>>1;
built(lson(t),l,mid);
built(rson(t),mid+1,r);
}
void update(int t,int s,int e,int c)
{
if(s-1==e)return;
if(segTree[t].color==c)return;
int l=segTree[t].l;
int r=segTree[t].r;
if(l>=s&&r<=e)///当前操作的区间是所有操作区间的子区间
{
segTree[t].color=c;
return;
}
if(segTree[t].color>=0)//存在颜色,往下更新
{
///即把当前节点的颜色pushdown给子节点
///最坏情况一直到单点 然后单点保存信息
segTree[lson(t)].color=segTree[t].color;
segTree[rson(t)].color=segTree[t].color;
// segTree[t].color=-2;//表示有多种颜色
}
int mid=(l+r)>>1;
///此处为区间更新 若为单点更新则无需考虑当前操作的区间和需要操作
///的区间之间的覆盖关系
if(s>mid)update(rson(t),s,e,c);
///事实证明 mid应该属于右边
else if(e<=mid)update(lson(t),s,e,c);
else
{
update(lson(t),s,mid,c);
update(rson(t),mid,e,c);
}
segTree[t].color=-2;///可以看做没有颜色和当前颜色这两种颜色?
}
int ans[N],tmp;
void cal(int t)
{
if(segTree[t].color==-1)///没颜色 直接走
{
tmp=-1;
return;
}
int c=segTree[t].color;
if(c!=-2)///只有一种颜色
{
if(c!=tmp)
{
ans[c]++;
tmp=c;
}
return;
}
if(segTree[t].l!=segTree[t].r)
{
cal(lson(t));
cal(rson(t));
}
}
int main()
{
int n,m,x,y,id;
n=N-5;
while(cin>>m)
{
memset(ans,0,sizeof(ans));
built(1,1,n);
while(m--)
{
cin>>x>>y>>id;
x++;///避免0的出现以及维护闭区间
n=max(n,id);
update(1,x,y,id);
}
tmp=-1;///最前面的前面是没有颜色的
cal(1);
for(int i=0;i<=n;i++)
{
if(ans[i])
cout<<i<<" "<<ans[i]<<endl;
}
cout<<endl;
}
return 0;
}