1. 程式人生 > >線段樹POJ - 2777

線段樹POJ - 2777

題意就是給你一段區間讓你塗顏色,或者一段區間讓你求顏色個數

對於每一種顏色,將其用二進位制狀態來記錄,合併的時候用 | 運算即可

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int N=100010;

struct node
{
    int l,r;
    int color;
    int flag;
} seg[N<<2];
void build(int rt,int L,int R)
{
    seg[rt].color
=1; seg[rt].l=L; seg[rt].r=R; seg[rt].flag=1; if(seg[rt].l==seg[rt].r) { return; } int mid=(L+R)/2; build(rt*2,L,mid); build(rt*2+1,mid+1,R); } void pushup(int rt) { seg[rt].color=seg[rt*2].color | seg[2*rt+1].color; } void pushdown(int
rt) { seg[rt*2].color=seg[rt].color; seg[rt*2].flag=1; seg[rt*2+1].color=seg[rt].color; seg[rt*2+1].flag=1; seg[rt].flag=0; } void update(int rt,int L,int R,int color) { if(seg[rt].l>=L&&seg[rt].r<=R) { seg[rt].color=color; seg[rt].flag
=1; return; } if(seg[rt].color==color) return; if(seg[rt].flag) pushdown(rt); int mid=(seg[rt].l+seg[rt].r)/2; if(R<=mid) update(rt*2,L,R,color); else if(L>=mid+1) update(rt*2+1,L,R,color); else { update(rt*2,L,mid,color); update(rt*2+1,mid+1,R,color); } pushup(rt); } int sum; void query(int rt,int L,int R) { if(seg[rt].l>=L&&seg[rt].r<=R) { sum|=seg[rt].color; return; } if(seg[rt].flag) { sum|=seg[rt].color; return; } int mid=(seg[rt].l+seg[rt].r)/2; if(R<=mid) { query(rt*2,L,R); } else if(L>=mid+1) { query(rt*2+1,L,R); } else { query(rt*2,L,mid); query(rt*2+1,mid+1,R); } } int solve() { int ans=0; while(sum) { if(sum&1) ans++; sum>>=1; } return ans; } int main() { int L,T,O,a,b,c; char op[4]; while(~scanf("%d%d%d",&L,&T,&O)) { build(1,1,L); while(O--) { scanf("%s",op); if(op[0]=='C') { scanf("%d%d%d",&a,&b,&c); if(a>b)swap(a,b); update(1,a,b,1<<(c-1)); } else { scanf("%d%d",&a,&b); if(a>b)swap(a,b); sum=0; query(1,a,b); printf("%d\n",solve()); } } } return 0; }