这道题,基本上可以算是线段树成段更新的基本操作练习的裸题了。主要是一个lazy-tag思想的应用。
注意边界条件不要搞错了。
其他就没什么了。
#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<string.h>
using namespace std;
const int N = 100000 + 10;
inline char Rstr(){char str[10]; scanf("%s",str); return str[0];}
int l,c,q;
struct node
{
int left,right;
bool lazy;
int col;
};
node seg_tree[N*4];
int hash(int x)
{
int res = 0;
// for(int i=0;i<=c;i++)
// {
// if(x&(1<<i))
// res ++;
// }
while(x)
{
x-=x&(-x);
res++;
}
return res;
}
void creattree(int l,int r,int rt)
{
seg_tree[rt].left = l;
seg_tree[rt].right = r;
seg_tree[rt].col = 1;
seg_tree[rt].lazy = false;
if(l==r) return;
int mid = (l+r)/2;
creattree(l,mid,rt<<1);
creattree(mid+1,r,rt<<1|1);
}
void update(int l,int r, int id,int rt)
{
if(seg_tree[rt].left>=l && seg_tree[rt].right<=r)
{
seg_tree[rt].lazy = true;
seg_tree[rt].col = (1<<(id-1));
return;
}
if(seg_tree[rt].lazy)
{
seg_tree[rt].lazy = false;
seg_tree[rt<<1].lazy = true;
seg_tree[rt<<1|1].lazy = true;
seg_tree[rt<<1].col = seg_tree[rt].col;
seg_tree[rt<<1|1].col = seg_tree[rt].col;
}
int mid = (seg_tree[rt].left + seg_tree[rt].right)/2;
if(r<=mid) update(l,r,id,rt<<1);
else if(mid+1<=l) update(l,r,id,rt<<1|1);
else
{
update(l,mid,id,rt<<1) ;
update(mid+1,r,id,rt<<1|1);
}
seg_tree[rt].col = (seg_tree[rt<<1].col | seg_tree[rt<<1|1].col);
}
int query(int l,int r,int rt)
{
if(seg_tree[rt].lazy) return seg_tree[rt].col;
if(seg_tree[rt].left==l && seg_tree[rt].right==r)
return seg_tree[rt].col;
int mid = (seg_tree[rt].left + seg_tree[rt].right)/2;
if(mid>=r) return query(l,r,rt<<1);
else if(mid+1<=l) return query(l,r,rt<<1|1);
else
return (query(l,mid,rt<<1) | query(mid+1,r,rt<<1|1));
}
int main()
{
while(scanf("%d%d%d",&l,&c,&q)==3)
{
creattree(1,l,1);
while(q--)
{
char ch = Rstr();
int x,y,z;
if(ch=='C')
{
scanf("%d%d%d",&x,&y,&z);
if(x>y) swap(x,y);
update(x,y,z,1);
}
else if(ch=='P')
{
scanf("%d%d",&x,&y);
if(x>y) swap(x,y);
printf("%d\n",hash(query(x,y,1)));
}
}
}
return 0;
}