题意:一个线段,长度为n,初始颜色是2。共m次操作,在某区间上画一种颜色或查询某区间的所有颜色(升序输出)。
思路:明显的线段树+lazy思想。和poj的某道题非常相似,以前做过,就很走运的迅速1A了。
#include <iostream>
#include <stdio.h>
#include <cmath>
#include <algorithm>
#include <iomanip>
#include <cstdlib>
#include <string>
#include <memory.h>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <ctype.h>
#define INF 1000000
using namespace std;
struct node{
int l;
int r;
int color;
bool flag;
};
node tree[4000001];
void built(int n,int l,int r){
tree[n].color=2;
tree[n].l=l;
tree[n].r=r;
tree[n].flag=true;
if(l!=r){
int mid=(l+r)/2;
built(n*2,l,mid);
built(n*2+1,mid+1,r);
}
}
void update(int n,int l,int r,int val){
if(l==tree[n].l&&r==tree[n].r){
tree[n].color=val;
tree[n].flag=true;
return;
}
int mid=(tree[n].l+tree[n].r)/2;
if(tree[n].flag){
update(n*2,tree[n].l,mid,tree[n].color);
update(n*2+1,mid+1,tree[n].r,tree[n].color);
}
tree[n].flag=false;
if(r<=mid){
update(n*2,l,r,val);
}else{
if(l>=mid+1){
update(n*2+1,l,r,val);
}else{
update(n*2,l,mid,val);
update(n*2+1,mid+1,r,val);
}
}
}
int query(int n,int l,int r){
if(tree[n].flag&&tree[n].l<=l&&tree[n].r>=r){
return tree[n].color;
}
int mid=(tree[n].l+tree[n].r)/2;
if(r<=mid){
return query(n*2,l,r);
}else{
if(l>=mid+1){
return query(n*2+1,l,r);
}else{
return query(n*2,l,mid)|query(n*2+1,mid+1,r);
}
}
}
int prt(int val){
int re=0;
int cnt=1;
bool fir=1;
while(val) {
if(val&1){
if(!fir)printf(" ");
fir=0;
printf("%d",cnt);
}
cnt++;
val>>=1;
}
return re;
}
int main(){
int L;//长度
int O;//操作数
while(cin>>L>>O){
if(L==0&&O==0)break;
built(1,1,L);
while(O--){
char oper;
cin>>oper;
if(oper=='P'){//更新
int A,B,C;
scanf("%d%d%d",&A,&B,&C);if(B<A)swap(A,B);
int col=1;
col<<=(C-1);
update(1,A,B,col);
}
if(oper=='Q'){//查询
int A,B;
scanf("%d%d",&A,&B);if(B<A)swap(A,B);
prt(query(1,A,B));
printf("\n");
}
}
}
return 0;
}