Description
画师傅又要开始画画了,这次他花了三天三夜将一堵墙涂成了白色。
但是画师傅有个顽劣的弟子小花,小花讨厌画师傅对Ta始乱终弃,所以趁 画师傅不在用不同的颜料将墙涂来涂去。
然而画师傅为了保护他的大作,设置了一个监控机制A。A每隔一段时间会 查珣某一段墙上的颜料的种类数,并将其记录下来。
现在画师傅回来了,看到五颜六色色彩斑斓灯火阑珊金碧辉煌的【哗】墙, 一口气没换上来,卒。
作为画师傅的好友杀小姐的你,为了追查画师傅的死因,于是调用了墙的监 控机制A的记录。于是,你看到了怎样的记录呢?
Solution
很显然,开30棵线段树即可,
但是:
有可能l>r啊!!!
白色是1啊!!!
复杂度:O(n∗30log(n));
要优化常数。
Code
#include<iostream>
#include<cstdio>
#include<cstdlib>
#define fo(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
const int N=100500;
int read(int &n)
{
char ch=' ';int q=0,w=1;
for(;(ch!='-')&&((ch<'0')||(ch>'9'));ch=getchar());
if(ch=='-')w=-1,ch=getchar();
for(;ch>='0' && ch<='9';ch=getchar())q=q*10+ch-48;n=q*w;return n;
}
int n,m,ans;
int b[N*3][32],la[N*3];
int s[32];
void doit(int l,int r,int e)
{
if(!la[e])return;
fo(i,0,m)b[e][i]=0;
b[e][la[e]]=r-l+1;
if(l!=r)la[e*2]=la[e],la[e*2+1]=la[e];
la[e]=0;
}
void build(int l,int r,int e)
{
if(l==r)
{
b[e][1]=1;
return;
}
int t=(l+r)/2;
build(l,t,e*2);
build(t+1,r,e*2+1);
b[e][1]=r-l+1;
}
void change(int l,int r,int e,int l1,int r1,int l2)
{
if(l==l1&&r==r1)
{
la[e]=l2;
doit(l,r,e);
return;
}
int t=(l+r)/2;
doit(l,t,e*2),doit(t+1,r,e*2+1);
if(r1<=t)change(l,t,e*2,l1,r1,l2);
else if(t<l1)change(t+1,r,e*2+1,l1,r1,l2);
else change(l,t,e*2,l1,t,l2),change(t+1,r,e*2+1,t+1,r1,l2);
fo(i,0,m)b[e][i]=b[e*2][i]+b[e*2+1][i];
}
void find(int l,int r,int e,int l1,int r1)
{
doit(l,r,e);
if(l==l1&&r==r1)
{
fo(i,0,m)s[i]+=b[e][i];
return;
}
int t=(l+r)/2;
if(r1<=t)find(l,t,e*2,l1,r1);
else if(t<l1)find(t+1,r,e*2+1,l1,r1);
else find(l,t,e*2,l1,t),find(t+1,r,e*2+1,t+1,r1);
}
int main()
{
int q,l,r,m_;
read(n),read(m),read(m_);
build(1,n,1);
while(m_--)
{
char ch=' ';
while(ch!='P'&&ch!='C')ch=getchar();
read(l),read(r);
if(r<l)swap(l,r);
if(ch=='C')
{
read(q);
change(1,n,1,l,r,q);
}
else
{
ans=q=0;
fo(i,0,m)s[i]=0;
find(1,n,1,l,r);
fo(i,1,m)if(s[i])ans++,q+=s[i];
printf("%d\n",ans+(q<r-l+1));
}
}
return 0;
}