POJ-2777Count Color 线段树+位移
2015-12-05 19:21
411 查看
这道题对于我这样的初学者还是有点难度的不过2遍A了还是很开心,下面说说想法……
Count Color
Time Limit: 1000MS Memory Limit: 65536K
Total Submissions: 40302 Accepted: 12161
Description
Chosen Problem Solving and Program design as an optional course, you are required to solve all kinds of problems. Here, we get a new problem.
There is a very long board with length L centimeter, L is a positive integer, so we can evenly divide the board into L segments, and they are labeled by 1, 2, … L from left to right, each is 1 centimeter long. Now we have to color the board - one segment with only one color. We can do following two operations on the board:
1. “C A B C” Color the board from segment A to segment B with color C.
2. “P A B” Output the number of different colors painted between segment A and segment B (including).
In our daily life, we have very few words to describe a color (red, green, blue, yellow…), so you may assume that the total number of different colors T is very small. To make it simple, we express the names of colors as color 1, color 2, … color T. At the beginning, the board was painted in color 1. Now the rest of problem is left to your.
Input
First line of input contains L (1 <= L <= 100000), T (1 <= T <= 30) and O (1 <= O <= 100000). Here O denotes the number of operations. Following O lines, each contains “C A B C” or “P A B” (here A, B, C are integers, and A may be larger than B) as an operation defined previously.
Output
Ouput results of the output operation in order, each line contains a number.
Sample Input
2 2 4
C 1 1 2
P 1 2
C 2 2 2
P 1 2
Sample Output
2
1
题目大意:
往画板上染色,画板长L(1<=L<=100000)颜色共有T种(1<=T<=30)给你O条操作(1<=O<=100000)操作分两种
(1)“C A B C”操作C:将【A,B】染成C色(开始时,画板都是颜色1)
(2)“P A B”操作P:【A,B】范围内颜色种数
最后再统计一下1的数目
下面是代码:
Count Color
Time Limit: 1000MS Memory Limit: 65536K
Total Submissions: 40302 Accepted: 12161
Description
Chosen Problem Solving and Program design as an optional course, you are required to solve all kinds of problems. Here, we get a new problem.
There is a very long board with length L centimeter, L is a positive integer, so we can evenly divide the board into L segments, and they are labeled by 1, 2, … L from left to right, each is 1 centimeter long. Now we have to color the board - one segment with only one color. We can do following two operations on the board:
1. “C A B C” Color the board from segment A to segment B with color C.
2. “P A B” Output the number of different colors painted between segment A and segment B (including).
In our daily life, we have very few words to describe a color (red, green, blue, yellow…), so you may assume that the total number of different colors T is very small. To make it simple, we express the names of colors as color 1, color 2, … color T. At the beginning, the board was painted in color 1. Now the rest of problem is left to your.
Input
First line of input contains L (1 <= L <= 100000), T (1 <= T <= 30) and O (1 <= O <= 100000). Here O denotes the number of operations. Following O lines, each contains “C A B C” or “P A B” (here A, B, C are integers, and A may be larger than B) as an operation defined previously.
Output
Ouput results of the output operation in order, each line contains a number.
Sample Input
2 2 4
C 1 1 2
P 1 2
C 2 2 2
P 1 2
Sample Output
2
1
题目大意:
往画板上染色,画板长L(1<=L<=100000)颜色共有T种(1<=T<=30)给你O条操作(1<=O<=100000)操作分两种
(1)“C A B C”操作C:将【A,B】染成C色(开始时,画板都是颜色1)
(2)“P A B”操作P:【A,B】范围内颜色种数
(此题有个蛋疼的地方,读入的AB可能顺序颠倒...也是略坑) 这道题用位移来做,如果染成t种颜色,就把颜色左移t-1位,位移运算在这道题里完美展现,所以以后还是得注重这种表示方法,了解多了,自然做题顺畅 用二进制表示对应的区间涂了第几种颜色,这样每个区间除了延迟标记外,可以再开一个数组统计当前涂了哪几种颜色。这样就和一般的线段树一样了。 (这种思想值得学习)
最后再统计一下1的数目
下面是代码:
//这波位移非常的nice啊! #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; #define maxl 100001 int color[maxl<<2]={0},sum[maxl<<2]={0}; void updata(int now) { sum[now]=sum[now<<1]|sum[now<<1|1]; }//or void pushdown(int now) { if (color[now]!=0) { color[now<<1]=color[now<<1|1]=color[now]; sum[now<<1]=color[now]; sum[now<<1|1]=color[now]; color[now]=0; } } void build(int l,int r,int now) { color[now]=1; if (l==r) return; int mid=(l+r)>>1; build(l,mid,now<<1); build(mid+1,r,now<<1|1); updata(now); } void change(int L,int R,int l,int r,int now,int newcolor) { if (L<=l && R>=r) { color[now]=1<<(newcolor-1); sum[now]=color[now]; return; }//位移表示颜色 int mid=(l+r)>>1; pushdown(now); if (L<=mid) change(L,R,l,mid,now<<1,newcolor); if (R>mid) change(L,R,mid+1,r,now<<1|1,newcolor); updata(now); } int query(int L,int R,int l,int r,int now) { if (L<=l && R>=r) return sum[now]; pushdown(now); int mid=(l+r)>>1; int ans=0; if (L<=mid) ans=ans|query(L,R,l,mid,now<<1); if (R>mid) ans=ans|query(L,R,mid+1,r,now<<1|1);//要对结果取or return ans; } int main() { int l,t,o; while(~scanf("%d%d%d",&l,&t,&o)) { build(1,l,1); for (int i=1; i<=o; i++) { char command[2]; int left,right,data; scanf("%s",&command); if (command[0]=='C') { scanf("%d%d%d",&left,&right,&data); if (left>right) { int temp=left; left=right; right=temp; } change(left,right,1,l,1,data); } else { scanf("%d%d",&left,&right); if (left>right) { int temp=left; left=right; right=temp; } int ans=query(left,right,1,l,1); int answer=0; while (ans>0) { if (ans & 1) answer++; ans=ans>>1; }//这里表示颜色数 printf("%d\n",answer); } } printf("\n"); } return 0; }
相关文章推荐
- 一张图理解继承关系
- 《两个二维数组(矩阵)相乘》
- iBatis多表查询
- 【查找结构1】静态查找结构概论
- 算法总结
- Module-Zero之租户管理
- IP数据报首部校验和算法
- 数据库连接问题解决方案
- css选择器特异性计算
- maven 配置和常用命令
- 分布式技术一周技术动态 2015.12.06
- 【转帖】C# DllImport 系统调用使用详解 托管代码的介绍 EntryPoint的使用
- 【转帖】.Net中C#的DllImport的用法
- Project Euler 95:Amicable chains 亲和数链
- Android语音识别——谷歌语音识别与百度语音识别
- 25匹马的角逐
- document.body与document.documentElement相关属性的区别
- swift注意点
- 第15周实践项目-直接插入排序
- 找零钱