zoukankan      html  css  js  c++  java
  • 【BZOJ2989】—数列(CDQ分治+曼哈顿距离转切比雪夫距离)

    传送门

    大意:定义2个位置的grazegraze值为两者位置差与数值差的和,即graze(x,y)=xy+a[x]a[y]graze(x,y)=|x-y|+|a[x]-a[y]|
    支持单点修改数值,询问所有出现过的数值与一个指定位置数的graze<=kgraze<=k的个数


    如果我们把位置看做xx,数值看做yy;
    那问题就变成了询问有多少个点距当前点的曼哈顿距离<=k<=k
    也就是对于一个斜着的正方形数点

    我们考虑把曼哈顿距离转变成切比雪夫距离,就变成了一个二维数点问题了

    直接上CDQCDQ分治

    也可以直接用mapmap暴力二位树状数组做,时空都是O(nlog2n)(unordered_map)O(nlog^2n)(unordered\_map)
    但不知道为什么总是有2个点RERE

    代码

    CDQCDQ

    #include<bits/stdc++.h>
    using namespace std;
    inline int read(){
    	char ch=getchar();
    	int res=0,f=1;
    	while(!isdigit(ch)){if(ch=='-')f=-f;ch=getchar();}
    	while(isdigit(ch))res=(res<<3)+(res<<1)+(ch^48),ch=getchar();
    	return res*f;
    }
    const int N=1000005;
    const int ext=100000;
    int n,q,cnt,tot,a[N],ans[N];
    struct ask{
    	int l,r,op,pos;
    }p[N];
    int tr[N];
    inline bool comp(const ask &a,const ask &b){
    	if(a.l==b.l)return a.r<b.r;
    	return a.l<b.l;
    }
    inline int lowbit(int x){
    	return (x&(-x));
    }
    inline void update(int pos,int k){
    	for(;pos<N;pos+=lowbit(pos))tr[pos]+=k;
    }
    inline int query(int pos,int res=0){
    	for(;pos;pos-=lowbit(pos))res+=tr[pos];return res;
    }
    char op[10];
    #define mid ((l+r)>>1)
    inline void cdq(int l,int r){
    	if(l==r)return;
    	cdq(l,mid),cdq(mid+1,r);
    	sort(p+l,p+mid+1,comp);
    	sort(p+mid+1,p+r+1,comp);
    	int i=l;
    	for(int j=mid+1;j<=r;j++){
    		for(;i<=mid&&p[i].l<=p[j].l;i++)
    			if(p[i].op==1)update(p[i].r,1);
    		if(p[j].op==2)ans[p[j].pos]+=query(p[j].r);
    	}
    	for(int j=l;j<i;j++)if(p[j].op==1)update(p[j].r,-1);
    }
    int main(){
    	n=read(),q=read();
    	for(int i=1;i<=n;i++){
    		a[i]=read();
    		int x=a[i]+i,y=i-a[i]+ext;
    		p[++tot].l=x,p[tot].r=y,p[tot].op=1;
    	}
    	for(int i=1;i<=q;i++){
    		scanf("%s",op);
    		int x=read(),k=read();
    		switch (op[0]){
    			case 'Q':{
    				int x1=a[x]+x,y1=x-a[x]+ext;
    				int x2=x1+k,y2=y1+k;x1-=k,y1-=k;
    				x1=max(x1,1),y1=max(y1,1);
    				p[++tot].l=x1-1,p[tot].r=y1-1,p[tot].pos=++cnt,p[tot].op=2;
    				p[++tot].l=x2  ,p[tot].r=y1-1,p[tot].pos=++cnt,p[tot].op=2;
    				p[++tot].l=x1-1,p[tot].r=y2  ,p[tot].pos=++cnt,p[tot].op=2;
    				p[++tot].l=x2  ,p[tot].r=y2  ,p[tot].pos=++cnt,p[tot].op=2;
    				break;
    			}
    			case 'M':{
    				a[x]=k,
    				p[++tot].l=a[x]+x,p[tot].r=x-a[x]+ext,p[tot].op=1;
    				break;
    			}
    		}
    	}
    	cdq(1,tot);
    	for(int i=1;i<=cnt;i+=4){
    		cout<<(ans[i]-ans[i+1]-ans[i+2]+ans[i+3])<<'
    ';
    	}
    }
    

    暴力mapmap(求dalaodalao看看为什么RERE)

    #include<bits/stdc++.h>
    #include<tr1/unordered_map>
    using namespace std;
    inline int read(){
    	char ch=getchar();
    	int res=0,f=1;
    	while(!isdigit(ch)){if(ch=='-')f=-f;ch=getchar();}
    	while(isdigit(ch))res=(res<<3)+(res<<1)+(ch^48),ch=getchar();
    	return res*f;
    }
    const int N=500005;
    const int ext=100001;
    using namespace tr1;
    unordered_map<int,int>tr[N];
    int n,q,a[N];
    inline int lowbit(int x){
    	return (x&(-x));
    }
    inline void update(int x,int y){
    	for(int i=x;i<N;i+=lowbit(i))
    		for(int j=y;j<N;j+=lowbit(j)){
    			if(!tr[i][j])tr[i][j]=1;
    			else tr[i][j]=tr[i][j]+1;
    			//cout<<x<<" "<<y<<'
    ';
    		}
    }
    inline int find(int x,int y){
    	int res=0;
    	for(int i=x;i;i-=lowbit(i))
    		for(int j=y;j;j-=lowbit(j))
    			res+=tr[i][j];
    	return res;
    }
    inline int query(int x1,int y1,int x2,int y2){
    	int res=0;x1=max(x1,1),y1=max(y1,1);
    	res=find(x1-1,y1-1);//cout<<res<<'
    ';
    	res+=find(x2,y2);//,cout<<res<<'
    ',
    	res-=find(x2,y1-1);//,cout<<res<<'
    ';
    	res-=find(x1-1,y2);
    	return res;
    }
    char op[10];
    int main(){
    	//freopen(";x.cpp","r",stdin);
    	n=read(),q=read();
    	for(int i=1;i<=n;i++){
    		a[i]=read();
    		update(i+a[i],i-a[i]+ext);
    	}
    	for(int i=1;i<=q;i++){
    		scanf("%s",op);
    		int x=read(),k=read();
    		switch(op[0]){
    			case 'Q':{
    				int x1=a[x]+x,y1=x-a[x]+ext;
    				cout<<query(x1-k,y1-k,x1+k,y1+k)<<'
    ';//cout<<"TRUN"<<'
    ';
    				break;
    			}
    			case 'M':{
    				a[x]=k,update(x+a[x],x-a[x]+ext);
    				break;
    			}
    		}
    	}
    }
    
  • 相关阅读:
    图像轮廓缺陷修补
    VS2005,VS2008,VS2010工程文件和解决方案的区别
    MFC中调用WPF教程
    Code::Blocks与wxWidgets安装配置——基于C++的免费IDE开发平台
    kalman 滤波 演示与opencv代码
    Predator:比微软Kinect更强的视频追踪算法来自捷克博士论文
    二值图像轮廓提取
    有用网址
    如何在Rich Edit Control中管理超链接
    坐标轴的平移与旋转
  • 原文地址:https://www.cnblogs.com/stargazer-cyk/p/10366314.html
Copyright © 2011-2022 走看看