您的位置:首页 > 其它

BZOJ 1176: [Balkan2007]Mokia | CDQ分治

2017-12-24 15:45 399 查看

题目:http://www.lydsy.com/JudgeOnline/problem.php?id=1176

 

题解:

题目s无用

 其实是CDQ还是能够看出来的,就是怎么做需要考虑考虑

首先对于一个区间的询问我们可以通过二维前缀和的方式转化成四个前缀询问,这样就可以用树状数组这类数据结构很快维护一维

然后把操作们按x坐标排序(x是第一维),这样树状数组就只用维护y轴信息即可

因为我们只用考虑一个序列中前半段时间修改对后半段时间答案的影响,所以树状数组维护一下y轴信息即可

#include<cstdio>
#include<algorithm>
#include<cstring>
#define M 2000010
using namespace std;
int s,w,op,x1,y1,x2,y2,cnt=1,ans[M],t[M],m;
struct Op
{
int type,t,x,y,k,id;
bool operator < (const Op &b)const
{
if (x==b.x && y==b.y) return type<b.type;
if (x==b.x) return y<b.y;
return x<b.x;
}
}p[M],tmp[M];
inline void AddQuery()
{
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
p[++cnt].id=++m;p[cnt].t=cnt,p[cnt].x=x1-1;p[cnt].y=y1-1;p[cnt].k=1;p[cnt].type=2;
p[++cnt].id=m;p[cnt].t=cnt,p[cnt].x=x2;p[cnt].y=y2;p[cnt].k=1;p[cnt].type=2;
p[++cnt].id=m;p[cnt].t=cnt,p[cnt].x=x1-1;p[cnt].y=y2;p[cnt].k=-1;p[cnt].type=2;
p[++cnt].id=m;p[cnt].t=cnt,p[cnt].x=x2;p[cnt].y=y1-1;p[cnt].k=-1;p[cnt].type=2;
}
inline void Insert(int x,int k)
{
for (;x<M;x+=x&-x) t[x]+=k;
}
inline int Query(int x)
{
int ret=0;
for (;x;x-=x&-x) ret+=t[x];
return ret;
}
inline void solve(int l,int r)
{
if (l==r) return ;
int mid=l+r>>1,i=l,j=mid+1;
for (int k=l;k<=r;k++)
if (p[k].t<=mid && p[k].type==1)
Insert(p[k].y,p[k].k);
else if (p[k].t>mid && p[k].type==2)
ans[p[k].id]+=p[k].k*Query(p[k].y);
for (int k=l;k<=r;k++)
{
if (p[k].t<=mid && p[k].type==1) Insert(p[k].y,-p[k].k);
if (p[k].t<=mid) tmp[i++]=p[k];
else tmp[j++]=p[k];
}
for (i=l;i<=r;i++)
p[i]=tmp[i];
solve(l,mid);
solve(mid+1,r);
}
int main()
{
printf("%d %d\n",p[0].t,p[1].t);
scanf("%d%d",&s,&w);
while (scanf("%d",&op)!=EOF && op!=3)
if (op==1)
scanf("%d%d%d",&p[cnt].x,&p[cnt].y,&p[cnt].k),p[cnt].type=1,p[cnt++].t=cnt++;
else AddQuery();
sort(p+1,p+1+cnt);
solve(1,cnt);
for (int i=1;i<=m;i++)
printf("%d\n",ans[i]);
return 0;
}

 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: