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
只会死套模板的我咋一看没什么想法,结合了之前区间修改的经验,借鉴了题解,发现其实还是个模板题……只不过换了个方式处理区间。
本题中两种操作一种是对特定区间涂色,一种是让算特定区间的颜色种数。解决涂色问题主要在于找出求和与涂色的异同。之前用到的区间求和即是通过将大区间分割,供查询区间求和。而涂色时思想基本相同,亦是将区间二分处理。若区间在修改区间范围内,则颜色变为修改色,若在区间范围外,则继续判断是完全与修改区间无交界,或者有交界。
无交界的结束判断,有交界的继续分割。由于颜色数量很少,最后剩下的颜色即通过数字标为1,不存在的颜色标为0,统计即可。
有一句废话:记得每次清楚标记颜色的数组。本来是个常识但是一下子没意识到这点还wa了几发……
#include <algorithm> #include <iostream> #include <sstream> #include <cstring> #include <cstdlib> #include <string> #include <vector> #include <cstdio> #include <cmath> #include <queue> #include <stack> #include <map> #include <set> using namespace std; #define INF 0x3f3f3f3 struct Node{ int left,right,num; }tree[400005]; int c1[35]; void build(int l,int r,int k){ tree[k].left=l; tree[k].right=r; tree[k].num=1; if (l>=r) return; int m=(l+r)/2; build(l, m, k*2); build(m+1, r, k*2+1); } void update(int l,int r,int k,int color){ if (tree[k].left>r||tree[k].right<l) { return; } if (l<=tree[k].left&&tree[k].right<=r) { tree[k].num=color; return; } if (tree[k].num) { tree[k*2].num=tree[k*2+1].num=tree[k].num; tree[k].num=0; } update(l, r, k*2, color); update(l, r, k*2+1, color); } void search(int l,int r,int k){ if (tree[k].left>r||tree[k].right<l) { return ; } if (tree[k].num) { c1[tree[k].num]=1; return; } search(l, r, k*2); search(l, r, k*2+1); } int main() { int t,n,o,a,b,c; char s[2]; scanf("%d%d%d",&n,&t,&o); build(1, n, 1); for (int i=0; i<o; i++) { scanf("%s",s); if (s[0]=='C') { scanf("%d %d %d",&a,&b,&c); update(a, b,1, c); } else { scanf("%d %d",&a,&b); memset(c1, 0, sizeof(c1)); int sum=0,t1; if (a>b) { t1=a; a=b; b=t1; } search(a,b,1); for (int i=1; i<=t; i++) { sum+=c1[i]; } printf("%d\n",sum); } } return 0; }