POJ2777
题解:
花了半天终于A了这一题,网上看了很多题解,代码风格和思路和常规的线段树风格都不一样,所以不想学。但最后终于找到合适自己的了。
一个记录颜色,一个lazy标志。多种颜色就用-1表示。然后就是push_down,push_up操作。详见代码,应该很好懂。
代码:
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
using namespace std;
int const N = 100000 + 10;
int const T = 30 + 5;
int n,t,m;
bool vis[T];
struct Node
{
int l,r,col,lazy;
void updata(int val){
col = val;
lazy = val;
}
}node[N<<2];
void push_up(int id){
if(node[id>>1].col == -1 || node[id<<1|1].col == -1)
node[id].col = -1;
else if(node[id<<1].col == node[id<<1|1].col)
node[id].col = node[id<<1].col;
else node[id].col = -1;
}
void push_down(int id){
int lazy = node[id].lazy;
if(lazy){
node[id<<1].updata(lazy);
node[id<<1|1].updata(lazy);
node[id].lazy = 0;
}
}
void build(int id,int l,int r){
node[id].l = l,node[id].r = r;
node[id].lazy = 0;
if(l == r){
node[id].col = 1;
return;
}
else{
int mid = (l + r) >> 1;
build(id<<1,l,mid);
build(id<<1|1,mid+1,r);
push_up(id);
}
}
void updata(int id,int L,int R,int k){ //将区间[L,R]的颜色更新为k
int l = node[id].l,r = node[id].r;
if(L <=l && r <= R){
node[id].updata(k);
return;
}
push_down(id);
int mid = (l + r) >> 1;
if(L <= mid) updata(id<<1,L,R,k);
if(mid < R) updata(id<<1|1,L,R,k);
push_up(id);
}
void query(int id,int L,int R){
int l = node[id].l,r = node[id].r;
if(node[id].col > 0){
vis[node[id].col] = true;
return;
}
push_down(id);
int mid = (l + r) >> 1;
if(L <= mid)query(id<<1,L,R);
if(mid < R)query(id<<1|1,L,R);
}
int main(){
scanf("%d%d%d",&n,&t,&m);
build(1,1,n);
char k;
int x,y,z;
for(int i=1;i<=m;i++){
scanf(" %c",&k);
if(k == 'C'){
scanf("%d%d%d",&x,&y,&z);
updata(1,min(x,y),max(x,y),z);
}else{
scanf("%d%d",&x,&y);
memset(vis,false,sizeof(vis));
query(1,min(x,y),max(x,y));
int ans = 0;
for(int i=1;i<=30;i++)
if(vis[i]) ans++;
printf("%d\n",ans);
}
}
return 0;
}
另解:状态压缩
原本觉得上面的方法特别好,但是做到CF620E,就TLE了。
所以就又学习了状态压缩的方法。很有收获,代码和上面的类似。
详细请见:https://blog.csdn.net/sg_siqing/article/details/12209027
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
using namespace std;
int const N = 100000 + 10;
int const T = 30 + 5;
int n,t,m;
struct Node
{
int l,r,col,lazy;
void updata(int val){
col = lazy = val;
}
}node[N<<2];
void push_up(int id){
node[id].col = node[id<<1].col | node[id<<1|1].col;
}
void push_down(int id){
int lazy = node[id].lazy;
if(lazy){
node[id<<1].updata(lazy);
node[id<<1|1].updata(lazy);
node[id].lazy = 0;
}
}
int lowbit(int x){return x&-x;}
int count(int t){
int c = 0;
while(t){
c++;
t -= lowbit(t);
}
return c;
}
void build(int id,int l,int r){
node[id].l = l,node[id].r = r;
node[id].lazy = 0;
if(l == r){
node[id].col = 2;
return;
}
else{
int mid = (l + r) >> 1;
build(id<<1,l,mid);
build(id<<1|1,mid+1,r);
push_up(id);
}
}
void updata(int id,int L,int R,int k){ //将区间[L,R]的颜色更新为k
int l = node[id].l,r = node[id].r;
if(L <=l && r <= R){
node[id].updata(k);
return;
}
push_down(id);
int mid = (l + r) >> 1;
if(L <= mid) updata(id<<1,L,R,k);
if(mid < R) updata(id<<1|1,L,R,k);
push_up(id);
}
int query(int id,int L,int R){
int l = node[id].l,r = node[id].r;
if(L <= l && r <= R) return node[id].col;
push_down(id);
int res = 0;
int mid = (l + r) >> 1;
if(L <= mid) res = query(id<<1,L,R);
if(mid < R) res |= query(id<<1|1,L,R);
return res;
}
int main(){
scanf("%d%d%d",&n,&t,&m);
build(1,1,n);
char k;
int x,y,z;
for(int i=1;i<=m;i++){
scanf(" %c",&k);
if(k == 'C'){
scanf("%d%d%d",&x,&y,&z);
updata(1,min(x,y),max(x,y),1<<z);
}else{
scanf("%d%d",&x,&y);
printf("%d\n",count(query(1,min(x,y),max(x,y))));
}
}
return 0;
}