数据范围过大,所以没有办法二维树状数组和二维线段树什么的。
听说kdtree可做?然而还不会。
这时候cdq分治就派上用场了,首先它不需要二维的空间,所有空间上是没问题的,然后时间复杂度也可以,具体时间复杂度分析下面再说。
这个问题其实可以看成一个三维偏序问题,(时间,横坐标,纵坐标)。
三维貌似看起来有些头疼,假如是二维呢,比如 问题是动态加点,询问一条线段里包含的权值和,
那样就是(时间,坐标)的一个二维偏序,对于我一个查询可以看成(a,b),(a,c)的两个偏序,a代表查询的时间,b,c代表线段的两个端点,那么我们如果找到时间小于a,坐标小于c的的权值和,再减去同样的比较方法小于(a,b)的权值和,不就求出了这一时刻这条线段里包含的权值和了嘛。
那么三维不就是把坐标扩大,按照求二维前缀和的方式去求容斥一下就好了?
我们需要先将一次询问转换为四次不同的二维前缀和查询操作,然后对于每一个询问,我们需要求出左区间(时间小于自己)里,横坐标小于自己纵坐标也小于自己的权值和,
时间已经满足,横坐标的话可以通过cdq分治时顺带的归并排序确定出横坐标小于自己的连续操作区间,但是纵坐标就需要用树状数组统计一下相应的权值了,在查询的时候再求出纵坐标小于自己的点的权值,每次分治的结束的时候都清空下树状数组,就做完了。
cdq分治递归logn层,每层o(n)的操作,然后加上一个树状数组的logn,时间复杂度就是nlog^nlog^2了。
cogs oj给出数据什么的真的好评,但是我数组开小了,应该re竟然返回wa了。
代码:
#include <stdio.h>
//using namespace std;
const int maxn=2e6+5;
int ans[10005];
struct node
{
int t;
int x;
int y;
int qid;
int val;
int type;
bool operator <(const node & a)const
{
return a.x==x?type<a.type:x<a.x;
}
}que[maxn], tmp[maxn];
int n;
int val[maxn];
int lowbit(int x)
{
return x&-x;
}
void add(int x, int y)
{
while(x<maxn)
{
val[x]+=y;
x+=lowbit(x);
}
return;
}
int sum(int x)
{
int res=0;
while(x>0)
{
res+=val[x];
x-=lowbit(x);
}
return res;
}
void cdq(int l, int r)
{
if(r-l<=1)return;
int mid=(l+r)>>1;
cdq(l, mid);
cdq(mid, r);
int p=l, q=mid, o=0;
// printf("%d %d\n", l, r);
while(p<mid && q<r)
{
if(que[p]<que[q])
{
if(que[p].type==1)
{
add(que[p].y, que[p].val);
}
tmp[o++]=que[p++];
}
else
{
if(que[q].type==2)
{
ans[que[q].qid]+=que[q].val*sum(que[q].y);
// printf("%d %d %d %d %d\n", que[q].x, que[q].y, que[q].val, que[q].qid, ans[que[q].qid]);
}
tmp[o++]=que[q++];
}
}
while(q<r)
{
if(que[q].type==2)
{
ans[que[q].qid]+=que[q].val*sum(que[q].y);
// printf("%d %d %d %d %d\n", que[q].x, que[q].y, que[q].val, que[q].qid, ans[que[q].qid]);
}
tmp[o++]=que[q++];
}
/*
memset(val, 0, sizeof val);
*/
for(int i=l; i<p; i++)if(que[i].type==1)add(que[i].y, que[i].val*-1);
while(p<mid)
{
tmp[o++]=que[p++];
}
for(int i=0; i<o; i++)que[i+l]=tmp[i];
return;
}
int main()
{
/*
freopen("mokia.in", "r", stdin);
freopen("mokia.out", "w", stdout);
*/
scanf("%*d%d", &n);
int x, y, x1, y1, e, id=1, qid=1;
while(~scanf("%d", &e))
{
if(e==3)break;
if(e==1)
{
scanf("%d%d%d", &que[id].x, &que[id].y, &que[id].val);
que[id].t=id;
que[id].type=1;
}
else
{
scanf("%d%d%d%d", &x, &y, &x1, &y1);
que[id].t=id, que[id].x=x-1, que[id].y=y-1, que[id].val=1, que[id].qid=qid, que[id].type=2;
id++;
que[id].t=id, que[id].x=x-1, que[id].y=y1, que[id].val=-1, que[id].qid=qid, que[id].type=2;
id++;
que[id].t=id, que[id].x=x1, que[id].y=y-1, que[id].val=-1, que[id].qid=qid, que[id].type=2;
id++;
que[id].t=id, que[id].x=x1, que[id].y=y1, que[id].val=1, que[id].qid=qid, que[id].type=2;
qid++;
}
id++;
}
cdq(1, id);
for(int i=1; i<qid; i++)
{
printf("%d\n", ans[i]);
}
}