[POJ 2777]Count Color 线段树+二进制状态压缩

【题目】

题目链接

Time Limit: 1000MS Memory Limit: 65536K
Total Submissions: 57935 Accepted: 17336

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

【题意】

一块板子,初始颜色为1。

有两种操作:“C” 把一段区间涂上一种颜色;“S"问区间有几种颜色。

【题解】

线段树板子题,但是自己想不到用二进制状态压缩qwq,老是忘

颜色用二进制位表示,有第i中颜色就把 第 i -1 位设为1

在涂的时候是把 覆盖到的点 sum 和 lazy 设为 1<< ( C - 1 )

update 的时候 用 或运算

query 的时候统计一下从0到t-1位 1个数。

【AC代码】

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
#define ln (node<<1)
#define rn (node<<1)|1
#define len  r-l+1
int const maxn=100005;
int a[maxn],z[maxn<<2],lazy[maxn<<2],lrange,rrange,ans,ns;
int n,t,o;
void add(int l,int r,int node,int x){
	lazy[node]=x;
	z[node]=x;//pushdown操作是把一整个直接设成
}
void pushdown(int l,int r,int node){//改为当前节点对,对下面的打标记
	if(!lazy[node])return ;
	int mid=(l+r)>>1;
	add(l,mid,ln,lazy[node]);
	add(mid+1,r,rn,lazy[node]);
	lazy[node]=0;
}
void change(int l,int r,int node){
	if(l>=lrange&&r<=rrange){
		lazy[node]=1<<ns;
		z[node]=1<<ns;
		return;
	}
	int mid=(l+r)>>1;
	pushdown(l,r,node);
	if(lrange<=mid)change(l,mid,ln);
	if(mid<rrange)change(mid+1,r,rn);
	z[node]=z[ln]|z[rn];
}
void query(int l,int r,int node){
	if(l>=lrange&&r<=rrange){
		ans|=z[node];
		return;
	}
	int mid=(l+r)>>1;
	pushdown(l,r,node);
	if(lrange<=mid)query(l,mid,ln);
	if(mid+1<=rrange)query(mid+1,r,rn);
}
inline int get_num(){
	int num=0;
	char ch;
	ch=getchar();
	while(ch<'0'||ch>'9')ch=getchar();
	while(ch>='0'&&ch<='9'){num=(num<<1)+(num<<3)+ch-'0';ch=getchar();}
	return num;
}
int main(){
	scanf("%d%d%d",&n,&t,&o);
	int m=n<<2;
	for(int i=1;i<=m;i++)z[i]=1,lazy[i]=0;	
	string s;
	while(o--){
		cin>>s;
		lrange=get_num();rrange=get_num();
		if(lrange>rrange)swap(lrange,rrange);//注意有 不按顺序给出
		if(s=="C"){
			ns=get_num()-1;
			change(1,n,1);
		}
		else{
			ans=0;
			query(1,n,1);
			int q=0;
			for(int i=0;i<t;i++)if(ans&(1<<i))q++;
			printf("%d
",q);
		}
	}
	return 0;
}
原文地址:https://www.cnblogs.com/conver/p/12255367.html