题意:n个位置,初始化全部为1号颜色。每次更新一段连续区间的颜色。计算所输入区间内的颜色数量。颜色种类数量在30之内。
解法:线段树。每次更新的时候区间能够恰好全部覆盖就停止向下递归(这是最关键的线段树所优化的地方)。注意在更新一些区间的时候,如果破坏了这个区间的完整性,则要将所有分段都向下更新。然后用状压的办法表示颜色数量(这在类似问题数量n不是很多的情况下使用很方便)。
代码:
#include <iostream>
#include <cstring>
#include <stdio.h>
using namespace std;
struct node
{
node *left,*right;
int l,r;
bool flag;
int color;
};
node nodes[300010];
int count1=0;
int L,T,o;
void buildtree(node *p,int l,int r)
{
p->l=l;p->r=r;
p->flag=true;
p->color=1;
if(l==r) return;
count1++;
p->left=nodes+count1;
count1++;
p->right=nodes+count1;
buildtree(p->left,l,(l+r)/2);
buildtree(p->right,(l+r)/2+1,r);
}
void update(int t,node *p,int l,int r)
{
//cout<<l<<" "<<r<<endl;
if(l==p->l&&r==p->r)
{
p->flag=true;
p->color=t;
return;
}
if(r<=(p->l+p->r)/2){
update(t,p->left,l,r);
if(p->flag)
{
p->flag=false;
if(l>p->l)
update(p->color,p->left,p->l,l-1);
if(r<(p->l+p->r)/2)
update(p->color,p->left,r+1,(p->l+p->r)/2);
update(p->color,p->right,(p->l+p->r)/2+1,p->r);
}
return ;
}
if(l>(p->l+p->r)/2){
update(t,p->right,l,r);
if(p->flag)
{
p->flag=false;
if(r<p->r)
update(p->color,p->right,r+1,p->r);
if(l-1>(p->l+p->r)/2)
update(p->color,p->right,(p->l+p->r)/2+1,l-1);
update(p->color,p->left,p->l,(p->l+p->r)/2);
}
return ;
}
update(t,p->left,l,(p->l+p->r)/2);
update(t,p->right,(p->l+p->r)/2+1,r);
if(p->flag)
{
if(l>p->l)update(p->color,p->left,p->l,l-1);
if(r<p->r)update(p->color,p->right,r+1,p->r);
p->flag=false;
}
}
int query(node *p,int l,int r)
{
//cout<<p->flag<<" "<<p->l<<" "<<p->r<<" "<<l<<" "<<r<<endl;
if(p->flag)
return p->color;
if(r<=(p->l+p->r)/2)
return query(p->left,l,r);
if(l>(p->l+p->r)/2)
return query(p->right,l,r);
return query(p->left,l,(p->l+p->r)/2)|query(p->right,(p->l+p->r)/2+1,r);
}
int main()
{
scanf("%d%d%d",&L,&T,&o);
buildtree(nodes,1,L);
while(o--)
{
char c;
cin>>c;
if(c=='C')
{
int l,r,color;
scanf("%d%d%d",&l,&r,&color);color--;
update((1<<color),nodes,l,r);
}
else
{
int l,r;
scanf("%d%d",&l,&r);
int tool=query(nodes,l,r); //cout<<tool<<endl;
int ans=0;
for(int i=0;i<T;i++)
if(tool&(1<<i))
ans++;
cout<<ans<<endl;
}
}
return 0;
}
/*
5 5 9
C 1 1 1
C 2 2 2
C 3 3 3
C 4 4 4
A 1 5
A 2 2
C 1 1 1
A 2 2
A 1 4
*/