P10633 BZOJ2989 数列/BZOJ4170 极光 题解

题目传送门

前置知识

CDQ 分治 | 权值树状数组及应用 | 曼哈顿距离与切比雪夫距离的相互转化

解法

增加一维为时间戳,那么操作 \(1\) 等价于单点加。

曼哈顿距离直接跑 CDQ 分治,貌似不太可做,考虑转化为切比雪夫距离。

  • 原曼哈顿坐标系中的点 \((x_{1},y_{1}),(x_{2},y_{2})\) 间的距离等价于切比雪夫坐标系中的 \((x_{1}+y_{1},x_{1}-y_{1}),(x_{2}+y_{2},x_{2}-y_{2})\)
  • \(|x_{1}-x_{2}|+|y_{1}-y_{2}|=\max(|x_{1}+y_{1}-x_{2}-y_{2}|,|x_{1}-y_{1}-x_{2}+y_{2}|)\),将左边的绝对值展开并进行归纳即可证明。

题意转化为求以 \((x,a_{x})\) 为中心的以 \(2k\) 为边长的正方形内点的个数,同 luogu P4390 [BalkanOI2007] Mokia 摩基亚 二维数点维护即可。

代码

#include<bits/stdc++.h>
using namespace std;
#define ll long long 
#define ull unsigned long long
#define sort stable_sort 
#define endl '\n'
struct node
{
	int t,x,y,pd,val,id;
	bool operator < (const node &another) const
	{
		return (x==another.x)?((y==another.y)?(pd>another.pd):(y<another.y)):(x<another.x);
	}
}a[500010],tmp[500010];
int ans[500010],y[500010],b[500010],cnt=0,q_cnt=0;
void add(int t,int x,int y,int pd,int val,int id)
{
	cnt++;
	a[cnt].t=t;
	a[cnt].x=x;
	a[cnt].y=y;
	a[cnt].pd=pd;
	a[cnt].val=val;
	a[cnt].id=id;
}
struct BIT
{
	int c[500010];
	int lowbit(int x)
	{
		return (x&(-x));
	}
	void add(int n,int x,int val)
	{
		for(int i=x;i<=n;i+=lowbit(i))
		{
			c[i]+=val;
		}
	}
	int getsum(int x)
	{
		int ans=0;
		for(int i=x;i>=1;i-=lowbit(i))
		{
			ans+=c[i];
		}
		return ans;
	}
}T;
void cdq(int l,int r,int k)
{
	if(l==r)
	{
		return;
	}
	int mid=(l+r)/2,x,y;
	cdq(l,mid,k);
	cdq(mid+1,r,k);
	sort(a+l,a+mid+1);
	sort(a+mid+1,a+r+1);
	for(x=l,y=mid+1;y<=r;y++)
	{
		for(;a[x].x<=a[y].x&&x<=mid;x++)
		{
			T.add(k,a[x].y,a[x].pd);
		}
		ans[a[y].id]+=a[y].val*T.getsum(a[y].y);
	}
	x--;
	for(int i=l;i<=x;i++)
	{
		T.add(k,a[i].y,-a[i].pd);
	}
}
int main()
{
	int n,m,x,k,i;
	string pd;
	cin>>n>>m;
	for(i=1;i<=n;i++)
	{
		cin>>y[i];
		add(0,i+y[i],i-y[i],1,0,0);
		b[0]++;
		b[b[0]]=i-y[i];
	}
	for(i=1;i<=m;i++)
	{
		cin>>pd;
		if(pd=="Modify")
		{
			cin>>x;
			cin>>y[x];
			add(i,x+y[x],x-y[x],1,0,0);
			b[0]++;
			b[b[0]]=x-y[x];
		}
		else
		{
			cin>>x>>k;
			q_cnt++;
			add(i,x+y[x]+k,x-y[x]+k,0,1,q_cnt);
			b[0]++;
			b[b[0]]=x-y[x]+k;
			add(i,x+y[x]-k-1,x-y[x]+k,0,-1,q_cnt);
			b[0]++;
			b[b[0]]=x-y[x]+k;
			add(i,x+y[x]+k,x-y[x]-k-1,0,-1,q_cnt);
			b[0]++;
			b[b[0]]=x-y[x]-k-1;
			add(i,x+y[x]-k-1,x-y[x]-k-1,0,1,q_cnt);
			b[0]++;
			b[b[0]]=x-y[x]-k-1;
		}
	}
	sort(b+1,b+1+b[0]);
	b[0]=unique(b+1,b+1+b[0])-(b+1);
	for(i=1;i<=cnt;i++)
	{	
		a[i].y=lower_bound(b+1,b+1+b[0],a[i].y)-b;
	}
	cdq(1,cnt,b[0]);
	for(i=1;i<=q_cnt;i++)
	{
		cout<<ans[i]<<endl;
	}
	return 0;
}
posted @ 2024-08-15 15:32  hzoi_Shadow  阅读(10)  评论(0编辑  收藏  举报
扩大
缩小