Solution & Code
题意是用
1...K
共
K
种颜色对一行共
这道题用带标记的线段树处理,对每个线段树节点记录三个标记:当前染色上界(lazy1)、当前染色下界(lazy2)、当前点及其儿子是否已经不合法(des),详见代码。
#include <cstdio>
#include <algorithm>
#include <iostream>
using namespace std;
const int maxn = 4e5 + 5;
int n, k, m, ans;
struct segment_tree{
int tot;
struct node{
int lazy1, lazy2, lson, rson; bool des;
}nd[maxn];
#define ls nd[i].lson
#define rs nd[i].rson
int build(int left, int rght){
int i = ++tot;
if(left != rght){
int mid = (left + rght) >> 1;
ls = build(left, mid);
rs = build(mid + 1, rght);
}
nd[i].lazy1 = nd[i].lazy2 = 0;
nd[i].des = false;
return i;
}
void pushdown(int i){
if(!ls && !rs) return;
if(nd[ls].lazy1 == 0) nd[ls].lazy1 = nd[i].lazy1, nd[ls].lazy2 = nd[i].lazy2;
else if(nd[ls].lazy2 + 1 == nd[i].lazy1) nd[ls].lazy2 = nd[i].lazy2;
else nd[ls].des = true;
if(nd[rs].lazy1 == 0) nd[rs].lazy1 = nd[i].lazy1, nd[rs].lazy2 = nd[i].lazy2;
else if(nd[rs].lazy2 + 1 == nd[i].lazy1) nd[rs].lazy2 = nd[i].lazy2;
else nd[rs].des = true;
nd[i].lazy1 = nd[i].lazy2 = 0;
}
void modify(int i, int left, int rght, int x, int y, int z){
if(nd[i].des) return;
if(nd[i].lazy1) pushdown(i);
if(x <= left && rght <= y){
if(!nd[i].lazy1) nd[i].lazy1 = nd[i].lazy2 = z;
else if(nd[i].lazy2 + 1 == z) nd[i].lazy2 = z;
else nd[i].des = true;
return;
}
int mid = (left + rght) >> 1;
if(ls && x <= mid) modify(ls, left, mid, x, y, z);
if(rs && y > mid) modify(rs, mid + 1, rght, x, y, z);
}
void shake(int i, int left, int rght){
if(nd[i].des) nd[ls].des = nd[rs].des = true;
if(nd[i].lazy1) pushdown(i);
if(!ls && !rs){
if(nd[i].des) return;
if(nd[i].lazy1 != 1) return;
if(nd[i].lazy2 != k) return;
++ans;
}
int mid = (left + rght) >> 1;
if(ls) shake(ls, left, mid);
if(rs) shake(rs, mid + 1, rght);
}
}st;
int main(){
scanf("%d%d", &n, &k);
scanf("%d", &m);
st.build(1, n);
for(int i = 1; i <= m; ++i){
int x, y, z;
scanf("%d%d%d", &x, &y, &z);
st.modify(1, 1, n, x, y, z);
}
st.shake(1, 1, n);
printf("%d\n", ans);
return 0;
}