Description
Input
Output
Sample Input
2 2 4 C 1 1 2 P 1 2 C 2 2 2 P 1 2
Sample Output
2 1
题目大意:操作是给给区间涂色(颜色种类小于30),询问指定区间颜色有多少种。
用状态压缩的方式记录颜色,然后就是比较标准的线段树了……
带lazy标记的线段树,其实也不难嘛……
#include <iostream> #include <string> #include <stdio.h> #include <cstring> using namespace std; struct ty{ int col; bool lazy; }tree[600010]; int t, o, l, sum; void build (int p, int l, int r) { tree[p].col = 1; tree[p].lazy = 1; if (l == r) return; int mid = (l + r) / 2; build(p * 2, l, mid); build(p * 2 + 1, mid + 1, r); } void push(int p) //标记向下传 { tree[p * 2].col = tree[p].col; tree[p * 2 + 1].col = tree[p].col; tree[p * 2].lazy = tree[p].lazy; tree[p * 2 + 1].lazy = tree[p].lazy; tree[p].lazy = 0; } void change(int p, int l, int r, int x, int y, int color) { if (x <= l && r <= y) //整个区间都要变——改动lazy标记即可 { tree[p].col = color; tree[p].lazy = 1; return; } if (tree[p].col == color) return ; if (tree[p].lazy) push(p); //传标记 int mid = (l + r) / 2; if (y <= mid) change(p * 2, l, mid, x, y, color); else if (x > mid) change(p*2+1, mid+1, r, x, y, color); else { change(p * 2, l, mid, x, mid, color); change(p*2+1, mid+1, r, mid + 1, y, color); } tree[p].col = tree[p*2].col | tree[p*2+1].col; } void find(int p, int l, int r, int x,int y) { if (x <= l && r <= y) { sum |= tree[p].col; return;} if (tree[p].lazy) {sum |= tree[p].col; return;} int mid = (l + r) / 2; if (y <= mid) find(p*2,l,mid,x,y); else if (x > mid) find(p*2+1,mid+1,r,x,y); else { find(p*2,l,mid,x,mid); find(p*2+1,mid+1,r,mid+1,y); } } int calc() { int ans = 0; while(sum){ if(sum & 1) ans++; sum >>= 1; } return ans; } int main() { while (scanf("%d%d%d", &l, &t, &o) != EOF) { build(1, 1, l); for (int i = 1; i <= o; i++) { char c; int x, y, z; scanf(" %c", &c); if (c == 'P') { scanf("%d%d", &x, &y); sum = 0; if (x > y) {int t = x; x = t; t=y;} find(1, 1, l, x, y); printf("%d\n",calc()); } else{ scanf("%d%d%d", &x, &y, &z); if (x > y) {int t = x; x = t; t=y;} change(1, 1, l, x, y, 1 << (z - 1)); } } } return 0; }