http://poj.org/problem?id=2777
题意:给你一个长板,宽度为l,t种颜色,o项操作。操作共两种,更新一个区间内的颜色,求一个区间内的颜色数量,输出。
思路:比较普通的成段更新,用mark统计颜色数量,不多说了。
#include <stdio.h>
#include <algorithm>
#include <stdlib.h>
#include <string.h>
#include <iostream>
using namespace std;
typedef long long LL;
const int N = 100010;
const int INF = 1e8;
struct line
{
int l;
int r;
int kind;
}tree[4 * N];
bool mark[N];
void build(int i, int l, int r)
{
tree[i].l = l;
tree[i].r = r;
tree[i].kind = 1;
if(l == r) return;
int mid = (l + r) >> 1;
build(i*2, l, mid);
build(i*2+1, mid+1, r);
}
void query(int i, int l, int r)
{
if(tree[i].kind > 0)
{
mark[tree[i].kind] = true;
return;
}
int mid = (tree[i].l + tree[i].r) >> 1;
if(mid >= r) query(i*2, l, r);
else if(mid < l) query(i*2+1, l, r);
else
{
query(i*2, l, mid);
query(i*2+1, mid+1, r);
}
}
void update(int i, int l, int r, int color)
{
if(tree[i].l == l && tree[i].r == r)
{
tree[i].kind = color;
return;
}
if(tree[i].kind != -1)//已经搜索到这一点了但没有执行上个条件就说明不是想要的结果,这个节点就没有价值了,将价值传到子节点
{
tree[i*2].kind = tree[i].kind;
tree[i*2+1].kind = tree[i].kind;
tree[i].kind = -1;
}
int mid = (tree[i].l + tree[i].r) >> 1;
if(mid >= r) update(i*2, l, r, color);
else if(mid < l) update(i*2+1, l, r, color);
else
{
update(i*2, l, mid, color);
update(i*2+1, mid+1, r, color);
}
}
int main()
{
// freopen("in.txt", "r", stdin);
int l, t, o, a, b, c;
char s[5];
scanf("%d%d%d", &l, &t, &o);
build(1, 1, l);
while(o--)
{
scanf("%s", s);
if(s[0] == 'C')
{
scanf("%d%d%d", &a, &b, &c);
if(a > b) swap(a, b);
update(1, a, b, c);
}
else if(s[0] == 'P')
{
scanf("%d%d", &a, &b);
if(a > b) swap(a, b);
memset(mark, false, sizeof(mark));
query(1, a, b);
int ans = 0;
for(int i = 1; i <= t; i++)
{
if(mark[i]) ans ++;
}
printf("%d\n", ans);
}
}
return 0;
}