题意:一个线段,长度为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; }