Description
**强烈吐槽坑人
辣鸡题目
区间可能左端点>右端点,白色的颜色用1表示!!!**
表示被坑啦!!!100分没啦!!!
辣鸡出题人,颓我比赛,毁我人生!!!
Analysis
显然,可以用开30颗线段树来卡一卡。结果我就900ms+强行碾过了。
Code
#include<cstdio>
#include<cstring>
#include<algorithm>
#define fo(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
const int N=100005;
int n,c,ans,lz[N*4];
bool tr[32][N*4],bz[32];
void build(int v,int l,int r)
{
if(l==r)
{
tr[1][v]=1;
return;
}
int mid=(l+r)>>1;
build(v+v,l,mid),build(v+v+1,mid+1,r);
tr[1][v]=1;
}
void update(int v,int z)
{
fo(i,1,30) tr[i][v]=0;
tr[z][v]=1;
lz[v]=z;
}
void down(int v)
{
if(!lz[v]) return;
update(v+v,lz[v]);
update(v+v+1,lz[v]);
lz[v]=0;
}
void change(int v,int l,int r,int x,int y,int z)
{
if(l==x && r==y)
{
update(v,z);
return;
}
down(v);
int mid=(l+r)>>1;
if(y<=mid) change(v+v,l,mid,x,y,z);
else
if(x>mid) change(v+v+1,mid+1,r,x,y,z);
else
change(v+v,l,mid,x,mid,z),change(v+v+1,mid+1,r,mid+1,y,z);
fo(i,1,30) tr[i][v]=tr[i][v+v] || tr[i][v+v+1];
}
void query(int v,int l,int r,int x,int y)
{
if(l==x && r==y)
{
fo(i,1,30)
if(!bz[i] && tr[i][v]) ans++,bz[i]=1;
return;
}
down(v);
int mid=(l+r)>>1;
if(y<=mid) query(v+v,l,mid,x,y);
else
if(x>mid) query(v+v+1,mid+1,r,x,y);
else
query(v+v,l,mid,x,mid),query(v+v+1,mid+1,r,mid+1,y);
}
int main()
{
char ch;
int _,x,y,z;
scanf("%d %d %d\n",&n,&c,&_);
build(1,1,n);
while(_--)
{
scanf("%c %d %d",&ch,&x,&y);
if(x>y) swap(x,y);
if(ch=='C')
{
scanf("%d\n",&z);
change(1,1,n,x,y,z);
}
else
{
scanf("\n");
ans=0;
memset(bz,0,sizeof(bz));
query(1,1,n,x,y);
printf("%d\n",ans);
}
}
return 0;
}