题意:
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; }