【題目大意】
現在有一個長度爲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、位運算
【不足】
可能線段樹還是醜了
貌似代碼的空格被篡改了一下,突然空格變多