题目链接:点击打开链接
大概意思就是给一个区间,然后多次操作给各个子区间涂色,颜色可覆盖,问最后各个颜色的区间有几段;
哇,线段树的又一种写法诶,dog,dog;
(神经病啊)
#include<iostream>
#include<algorithm>
#include<string>
#include<queue>
#include<cmath>
#include<vector>
#include<stdlib.h>
#include<iomanip>
#include<list>
#include<stack>
#include<memory.h>
#include<ctype.h>
using namespace std;
typedef long long ll;
const int maxn = 8000 + 5;
struct node
{
int l, r;
int color;
};
node tree[maxn*3];
int color[maxn];//计数数组
void init(int l, int r, int pos) {
tree[pos].l = l;
tree[pos].r = r;
tree[pos].color = -1;//-1表示没有颜色
if (l == r - 1) return;
int mid = (l + r) >> 1;
init(l, mid, pos << 1);
init(mid, r, pos << 1 | 1);
}
void updata(int pos, int l, int r, int val) {
//更新区间l-r的信息,pos:节点位置,val:颜色
if (l == r)return;
if (tree[pos].color == val)return;
if (l <= tree[pos].l&&r >= tree[pos].r) {
tree[pos].color = val;
return;
}
if (tree[pos].color >= 0) {//存在颜色,标记下推
tree[pos << 1].color = tree[pos].color;
tree[pos << 1|1].color = tree[pos].color;
tree[pos].color =-2;//该节点已经下推过,标记清空
}
int mid = (tree[pos].l + tree[pos].r) >> 1;
if (r <= mid)updata(pos << 1, l, r, val);
else if (l >= mid)updata(pos << 1 | 1, l, r, val);
else {
updata(pos << 1, l, mid, val);
updata(pos << 1 | 1, mid, r, val);
}
tree[pos].color = -2;//该节点不需要再下推
}
int temp;
void count(int pos) {
//统计各颜色的段数
if (tree[pos].color == -1) {
temp = -1;
return;
}
if (tree[pos].color != -2) {
if (tree[pos].color != temp) {
color[tree[pos].color]++;
temp = tree[pos].color;//temp保存前一段的颜色
}
return;
}
if (tree[pos].l != tree[pos].r - 1) {
count(pos << 1);
count(pos << 1 | 1);
}
}
int main() {
int n, a, b, c;
int num;
while (scanf("%d", &n) != EOF) {
init(0,8000, 1);
num = 0;
while (n--) {
scanf("%d%d%d", &a, &b, &c);
updata(1, a, b, c);
if (c > num)num = c;
}
temp = -1;//temp初始化
memset(color, 0, sizeof(color));
count(1);
for (int i = 0; i <= num; i++) {
if (color[i])printf("%d %d\n", i, color[i]);
}
printf("\n");
}
return 0;
}