发现任何时刻不会出现两片颜色相同的云朵,因此云朵的颜色是不用考虑的,询问即为区间内有多少个云朵。
因为云朵的运动是在天空中往返的,具有周期性,且每个云朵运动速度都相同,所以可以用二元组 ((time,lenth)) 来表示一个云朵,(time) 为该云朵左端点位于左边界时的时刻,即 (t-ld mod 2len),(lenth) 为该云朵的长度,即 (r-l),发现每个云朵都能用二维平面上的点 ((x,y)) 来表示。
接着考虑如何解决询问 ((t,l,r)),首先对 (t) 转化为 (t mod 2len)。然后通过分类讨论来找到对于该询问在二维平面上对应的位置。设云朵的坐标为 ((x,y)),得:
当 (t geqslant x) 时,该云朵要到达询问的时刻还需再经过一段时间,经过这些时间后云朵的左端点要在询问的右端点左边,即 (t-x leqslant r),云朵的右端点要在询问的左端点右边,即 (t-x+y geqslant l)。
当 (t < x) 时,该云朵已经超过询问的时刻,因此其需要时光倒流,因为运动的周期性,其还是向右运动,把这些时间倒流后云朵的左端点要在询问的右端点左边,即 (x-t leqslant r),云朵的右端点要在询问的左端点右边,即 (x-t+y geqslant l)。
综上所述得询问在二维平面上对应的位置为 (t-r leqslant x leqslant t+r,| x-t | +y geqslant l),在平面上画出图来得:
发现图像为两个对称的五边形,若其超出了边界,就在另一端补上来,对于该图像不好进行统计,因此还需再进行转化,将其补成平行四边形得:
然后考虑对这两个平行四边形转化为矩形来进行统计,因为是询问存在性,而不是面积之类的信息,所以对于询问的范围进行转化,对于每个云朵的坐标也进行转化,然后进行询问就是合法的。对于右边向右倾斜的平行四边形,对其应用变换 ((x,y) Rightarrow (x,x+y)),对于左边向左倾斜的平行四边形,对其应用变换 ((x,y) Rightarrow (x,y-x+2len)),这里加上 (2len) 的原因是防止出现负坐标。然后对于这两个平行四边形分别用两个二维树状数组来维护,每个云朵在树状数组上进行加点删点时也应用相应的变换即可。
注意到当询问出现 (r=len) 的情况时,(t-r) 和 (t+r) 这两个位置会算重,因此需要特判。
#include<bits/stdc++.h>
#define maxn 4010
#define maxm 1000010
#define lowbit(x) (x&(-x))
using namespace std;
template<typename T> inline void read(T &x)
{
x=0;char c=getchar();bool flag=false;
while(!isdigit(c)){if(c=='-')flag=true;c=getchar();}
while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
if(flag)x=-x;
}
int n,len;
struct node
{
int x,y;
}p[maxm];
struct BIT
{
int t[maxn][maxn];
void update(int x,int y,int v)
{
for(int i=x+1;i<=2*len;i+=lowbit(i))
for(int j=y+1;j<=4*len;j+=lowbit(j))
t[i][j]+=v;
}
int ask(int x,int y)
{
if(x<0||y<0) return 0;
int v=0;
for(int i=min(x+1,2*len);i;i-=lowbit(i))
for(int j=min(y+1,4*len);j;j-=lowbit(j))
v+=t[i][j];
return v;
}
int query(int x1,int y1,int x2,int y2)
{
return ask(x2,y2)-ask(x2,y1-1)-ask(x1-1,y2)+ask(x1-1,y1-1);
}
}T1,T2;
int main()
{
read(n),read(len);
for(int i=1;i<=n;++i)
{
int opt,t,c,l,r,d,v=0;
read(opt);
if(opt==1)
{
read(t),read(c),read(l),read(r),read(d);
p[c].x=(t-l*d+2*len)%(2*len),p[c].y=r-l;
T1.update(p[c].x,p[c].x+p[c].y,1),T2.update(p[c].x,p[c].y-p[c].x+2*len,1);
}
if(opt==2)
{
read(t),read(l),read(r),d=(r==len),t%=2*len;
v+=T1.query(t,t+l,t+r-d,4*len);
v+=T1.query(0,t+l-2*len,t+r-2*len,4*len);
v+=T2.query(t-r+d,l-t+2*len,t-1,4*len);
v+=T2.query(t-r+2*len,l-t,2*len,4*len);
printf("%d
",v);
}
if(opt==3)
{
read(t),read(c);
T1.update(p[c].x,p[c].x+p[c].y,-1),T2.update(p[c].x,p[c].y-p[c].x+2*len,-1);
}
}
return 0;
}