Description
Solution
辣鸡题目!!!
(这里就不骂辣鸡出题人了)
这题查询和修改区间
(l,r)
竟然
l
可以大于r !!
而且白色是颜料1!!!!
注意上面那些细节,开30颗线段树就可以AC了。
Code
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#define fo(i,j,k) for(int i=j;i<=k;i++)
#define fd(i,j,k) for(int i=j;i>=k;i--)
#define N 100001
using namespace std;
bool tr[N*4][31];
int g[N*4];
int a[N];
bool bz[31];
int n,c,m;
void put(int v,int l,int r)
{
if(!g[v]) return;
fo(i,1,c) tr[v*2][i]=tr[v*2+1][i]=0;
tr[v*2][g[v]]=1;
tr[v*2+1][g[v]]=1;
g[v*2]=g[v*2+1]=g[v];
g[v]=0;
}
void build(int v,int l,int r)
{
if(l==r)
{
tr[v][1]=1;
g[v]=0;
return;
}
int mid=(l+r)/2;
build(v*2,l,mid);
build(v*2+1,mid+1,r);
tr[v][1]=tr[v*2][1]|tr[v*2+1][1];
g[v]=0;
}
void change(int v,int l,int r,int x,int y,int t)
{
if(l==x && r==y)
{
g[v]=t;
fo(i,1,c) tr[v][i]=0;
tr[v][t]=1;
return;
}
put(v,l,r);
int mid=(l+r)/2;
if(y<=mid) change(v*2,l,mid,x,y,t);
else if(x>mid) change(v*2+1,mid+1,r,x,y,t);
else
{
change(v*2,l,mid,x,mid,t);
change(v*2+1,mid+1,r,mid+1,y,t);
}
fo(i,1,c)
tr[v][i]=tr[v*2][i]|tr[v*2+1][i];
}
int ans=0;
void find(int v,int l,int r,int x,int y)
{
if(l==x && r==y)
{
fo(i,1,c)
if(tr[v][i] && !bz[i]) bz[i]=true,ans++;
return;
}
put(v,l,r);
int mid=(l+r)/2;
if(y<=mid) find(v*2,l,mid,x,y);
else if(x>mid) find(v*2+1,mid+1,r,x,y);
else
{
find(v*2,l,mid,x,mid);
find(v*2+1,mid+1,r,mid+1,y);
}
}
int main()
{
cin>>n>>c>>m;
build(1,1,n);
while(m--)
{
char ch[3];
int l,r;
scanf("%s %d %d",ch,&l,&r);
if(l>r) swap(l,r);
if(ch[0]=='C')
{
int t;
scanf("%d",&t);
change(1,1,n,l,r,t);
}
else
{
memset(bz,0,sizeof(bz));
ans=0;
find(1,1,n,l,r);
if(!ans) ans++;
printf("%d\n",ans);
}
}
}