题目链接:
http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=610
题意:
题解:
线段树区间更新
注意更新子节点,如果遇到的父节点已经被颜色覆盖掉的话,父节点 的颜色需要往下传递(因为父节点已经不会是原来那种颜色了)。
代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define MS(a) memset(a,0,sizeof(a))
#define MP make_pair
#define PB push_back
const int INF = 0x3f3f3f3f;
const ll INFLL = 0x3f3f3f3f3f3f3f3fLL;
inline ll read(){
ll x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
//////////////////////////////////////////////////////////////////////////
const int maxn = 8e3+10;
struct node{
int l,r,col,lazy;
}t[maxn<<2];
void build(int rt,int l,int r){
t[rt].l=l,t[rt].r=r,t[rt].col=-1,t[rt].lazy=-1;
if(l == r) return ;
int mid = (l+r)/2;
build(rt<<1,l,mid);
build(rt<<1|1,mid+1,r);
}
void pushdown(int rt){
if(t[rt].lazy != -1){
t[rt<<1].lazy=t[rt<<1|1].lazy = 1;
t[rt<<1].col = t[rt].col;
t[rt<<1|1].col = t[rt].col;
t[rt].lazy = t[rt].col = -1;
}
}
void update(int rt,int l,int r,int c){
int L=t[rt].l,R=t[rt].r;
if(l<=L && R<=r) {
t[rt].col = c;
t[rt].lazy = 1;
return ;
}
if(t[rt].col == c) return ;
pushdown(rt);
int mid = (L+R)/2;
if(l<=mid) update(rt<<1,l,r,c);
if(r>mid) update(rt<<1|1,l,r,c);
}
int vis[maxn<<2],ans[maxn<<2];
void query(int rt){
int l = t[rt].l,r=t[rt].r;
if(t[rt].lazy == 1){
int c = t[rt].col;
for(int i=l; i<=r; ++i)
vis[i] = c;
return ;
}
if(l == r) return ;
query(rt<<1);
query(rt<<1|1);
}
int main(){
int n;
while(cin>>n){
build(1,1,maxn);
for(int i=0; i<n; i++){
int l,r,c; cin>>l>>r>>c;
update(1,l+1,r,c);
// 题目每次给的染色段是把[a,b]染成c,之前一直以为就是把a~b的所有点都染成c, 其实不是这样的,
// 要染色的不是点,而是区间,例如要染[0,1],并不是把0,1两点染色,而是把[0,1]这一个单位
// 区间进行染色。 假设有一个样例:
// 1 2 1
// 3 4 1
// 那么这个样例应该输出 1 2 只需要在纸上画一下就可以发现,区间【2,3】是没有被染色的,
// 所以有两个间断的区间颜色是1。
// 解决这个问题的办法是,建立线段树build(1,1,8000),代表区间1~8000,
// 然后更新时是update(1,1,8000, a+1,b,c);
}
memset(vis,-1,sizeof(vis));
query(1);
int i = 1;
MS(ans);
while(i<maxn){
int color=vis[i], j=i+1;
if(color==-1){++i; continue;}
while(vis[j]!=-1 && vis[j]==color && j<maxn) ++j; // 统计的是点。。
++ans[color];
i=j;
}
for(int i=0; i<maxn; ++i)if(ans[i])
printf("%d %d\n",i,ans[i]);
puts("");
}
return 0;
}