【题目大意】
现在有一个长度为L cm的板,每一厘米划分成一个格子,一开始每个格子颜色涂为1(1号颜色),之后有O个操作,一共有两种操作:
1、C a b c 代表将区间[a,b]全部刷成c颜色(一共有T种颜色,会读入)
2、P a b 代表询问区间[a,b]有多少种不同的颜色
数据范围:1<=L<=1e5,1<=T<=30,1<=O<=1e5
注意可能读入的a,b出现a>b的情况,需要交换一下;
【解题思路】(虽然我A了但是貌似时间和空间都用的比较多)
很容易看出本题目是线段树的题目,主要是稍微处理一下颜色的合并,本题可以使用位运算“|”来进行统计
【代码】
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<ctime>
#include<cstring>
#include<string>
#include<cctype>
#include<iomanip>
#include<map>
//#define LOCAL
#define LL long long
using namespace std;
const int N=100101;
int m,n,q;
int sum;
struct Seg_Tree{
struct treenode{
int l,r;
int color;
bool lazy;
void Update(int v){
color=v;
lazy=true;
}
}tree[N<<2];
void UnleashLabel(int o){
tree[o<<1].color=tree[o].color;
tree[o<<1|1].color=tree[o].color;
tree[o<<1].lazy=true;
tree[o<<1|1].lazy=true;
tree[o].lazy=false;
}
void Maintain(int o){
tree[o].color=tree[o<<1].color|tree[o<<1|1].color;
}
void Build(int o,int l,int r){
tree[o].l=l;
tree[o].r=r;
tree[o].color=1;
tree[o].lazy=true;
if (l==r) return;
int mid=(l+r)>>1;
Build(o<<1,l,mid);
Build(o<<1|1,mid+1,r);
}
void Overlap(int o,int ql,int qr,int v){
int l=tree[o].l;
int r=tree[o].r;
if (ql<=l&&qr>=r){
tree[o].Update(v);
return;
}
if (tree[o].color==v) return;
if (tree[o].lazy) UnleashLabel(o);
int mid=(l+r)>>1;
if (qr<=mid) Overlap(o<<1,ql,qr,v);
else if (ql>mid) Overlap(o<<1|1,ql,qr,v);
else{
Overlap(o<<1,ql,mid,v);
Overlap(o<<1|1,mid+1,qr,v);
}
Maintain(o);
}
void Query(int o,int ql,int qr){
int l=tree[o].l;
int r=tree[o].r;
if ((ql<=l&&qr>=r)||tree[o].lazy){
sum|=tree[o].color;
return;
}
else{
int mid=(l+r)>>1;
if (qr<=mid) Query(o<<1,ql,qr);
else if (ql>mid) Query(o<<1|1,ql,qr);
else{
Query(o<<1,ql,mid);
Query(o<<1|1,mid+1,qr);
}
}
}
}SgTree;
int Getans(){
int ans=0;
while (sum){
if (sum&1) ans++;
sum>>=1;
}
return ans;
}
int main(){
#ifdef LOCAL
freopen("POJ2777.in","r",stdin);
#endif
while (scanf("%d%d%d",&m,&n,&q)!=EOF){
SgTree.Build(1,1,m);
char ch[3];
while (q--){
scanf("%s",&ch[0]);
if (ch[0]=='C'){
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
if (x>y) swap(x,y);
SgTree.Overlap(1,x,y,1<<(z-1));
}
else{
int x,y;
scanf("%d%d",&x,&y);
if (x>y) swap(x,y);
sum=0;
SgTree.Query(1,x,y);
printf("%d\n",Getans());
}
}
}
return 0;
}
【总结】
1、简单线段树
2、位运算
【不足】
可能线段树还是丑了
貌似代码的空格被篡改了一下,突然空格变多