题意:
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;
} 
京公网安备 11010502036488号