BZOJ2989 数列【cdq分治】

darkbzoj


SOL

  • 据说可以对修改二进制分组+主席树在线做? 学学吧。。。

  • 先把曼达顿距离转化成切尔雪夫距离,即:

  • ∣ x 1 − x 2 ∣ + ∣ y 1 − y 2 ∣ ≤ k |x_1-x_2|+|y_1-y_2|\le k x1x2+y1y2k 转化为 m a x ( ∣ x 1 ′ − x 2 ′ ∣ , ∣ y 1 ′ − y 2 ′ ∣ ) ≤ k max(|x_1'-x_2'|,|y_1'-y_2'|)\le k max(x1x2,y1y2)k其中 x 1 ′ = x 1 + y 1 , y 1 ′ = x 1 − y 1 x_1'=x_1+y_1,y_1'=x_1-y_1 x1=x1+y1,y1=x1y1

  • 然后成为了带修改的二维数点,cdq分治即可


CODE

#include<bits/stdc++.h>
using namespace std;
#define sf scanf
#define pf printf
#define ll long long
#define cs const
#define db double
#define ri register int
#define gc getchar()
#define in red()
inline int red(){
	int num=0,f=1;char c=gc;
	for(;!isdigit(c);c=gc)if(c=='-')f=-1;
	for(;isdigit(c);c=gc)num=(num<<1)+(num<<3)+(c^48);
	return num*f;
}
#define lb(x) (x&(-x))
cs int N=1e6+100,mov=3e5+10,lim=6e5+30;
int sum[N];
inline void up(int k,int v){for(;k<=lim;k+=lb(k))sum[k]+=v;}
inline int qy(int k){int ans=0;for(;k;k-=lb(k))ans+=sum[k];return ans;}
struct op{
	int tim,x,y,d,sy,id;
	inline bool operator <(cs op &t){
		return x==t.x ? d>t.d : x<t.x;		
	}
}q[N],tmp[N];
int top=0,ans[N],tot,n,m,a[N],cnt=0;
inline void cdq(int l,int r){
	if(l==r)return;
	int mid=(l+r)>>1;
	cdq(l,mid);cdq(mid+1,r);
	top=0;
	for(ri i=l;i<=r;++i)tmp[++top]=q[i];
	sort(tmp+1,tmp+top+1);
	for(ri i=1;i<=top;++i){
		if(tmp[i].tim<=mid&&tmp[i].d==2)up(tmp[i].y,1);
		if(tmp[i].tim>mid&&tmp[i].d^2){
			ans[tmp[i].id]+=tmp[i].d*(qy(tmp[i].y)-qy(tmp[i].sy-1));
		}
	}
	for(ri i=1;i<=top;++i){
		if(tmp[i].tim<=mid&&tmp[i].d==2)up(tmp[i].y,-1);
	}
}
char s[20];
signed main(){
//	freopen("data.in","r",stdin);
	n=in;m=in;
	for(ri i=1;i<=n;++i){
		a[i]=in;++tot;
		q[tot]=(op){tot,i+a[i]+mov,i-a[i]+mov,2,0,0};
	}
	while(m--){
		sf("%s",s);int x=in,k=in;
		if(s[0]=='M'){
			a[x]=k;
			++tot;q[tot]=(op){tot,x+k+mov,x-k+mov,2,0,0};
		}
		if(s[0]=='Q'){
			++cnt;
			++tot;q[tot]=(op){tot,x+a[x]-k-1+mov,x-a[x]+mov+k,-1,x-a[x]+mov-k,cnt};
			++tot;q[tot]=(op){tot,x+a[x]+k+mov,x-a[x]+mov+k,1,x-a[x]+mov-k,cnt};
		}
	}
	cdq(1,tot);
	for(ri i=1;i<=cnt;++i)cout<<ans[i]<<'\n';


	return 0;
}














  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值