题意:
n次操作,每次给出x1,x2,c,表示在区间[x1,x2]上涂上颜色c,如果能看到颜色i,就输出i并输出颜色i有几个不相交的区间。

思路:
对于线段而言,如果长度大于等于1,它的两端被别的颜色占了,那么这个颜色还是能看到的。但如果涂区间内的点,如果长度等于1,它的两端被别的颜色占了,那么这个颜色是看不到的(线段树可以处理这种情况)。
对输入的x1、x2扩大两倍,使得涂线段问题变成涂点的问题,便于线段树维护。

Code:

#include<algorithm>
#include<cstring>
#include<cstdio>
#include<iostream>
using namespace std;
typedef long long ll;
const int maxn=8007<<1;
inline ll read() {
    ll s = 0, w = 1;
    char ch = getchar();
    while (ch < 48 || ch > 57) {
        if (ch == '-') w = -1;
        ch = getchar();
    }
    while (ch >= 48 && ch <= 57)
        s = (s << 1) + (s << 3) + (ch ^ 48), ch = getchar();
    return s * w;
}
int tree[maxn<<2],a[maxn],pos[maxn];
inline void pushdown(int rt) {
    tree[rt<<1]=tree[rt<<1|1]=tree[rt];
    tree[rt]=-1;
}
inline void update(int x,int y,int val,int l,int r,int rt) {
    if(x<=l&&y>=r) {
        tree[rt]=val;
        return;
    }
    int mid=l+r>>1;
    if(~tree[rt]) pushdown(rt);
    if(x<=mid) update(x,y,val,l,mid,rt<<1);
    if(y>mid) update(x,y,val,mid+1,r,rt<<1|1);
}
inline void query(int l,int r,int rt) {
    if(~tree[rt]) {
        if(l-pos[tree[rt]]>1) a[tree[rt]]+=1;
        pos[tree[rt]]=r;
        return;
    }
    if(l==r) return;
    int mid=l+r>>1;
    if(~tree[rt]) pushdown(rt);
    query(l,mid,rt<<1);
    query(mid+1,r,rt<<1|1);
}
int main() {
    int n,x,y,z;
    while(~scanf("%d",&n)) {
        memset(tree,-1,sizeof tree);
        fill(pos,pos+maxn,-2);
        memset(a,0,sizeof a);
        while(n--) {
            x=read(),y=read(),z=read();
            update(x<<1,y<<1,z,0,maxn,1);
        }
        query(0,maxn,1);
        for(int i=0;i<maxn;++i) if(a[i]) {
            printf("%d %d\n",i,a[i]);
        }
        printf("\n");
    }
    return 0;
}