• 201⑨湘潭邀请赛 Chika and Friendly Pairs(HDU6534)


    原题链接:http://acm.hdu.edu.cn/showproblem.php?pid=6534

    题意:

    给你一个数组,对于第i个数来说,如果存在一个位置j,使得j>i并且a[j]-k<=a[i]<=a[j]+k,那么这对数就称为好的,有q个询问,问你l到r区间有多少对好的数。

    思路:

    离线询问,想到可以用莫队维护区间,新加入元素(或删除元素)x时要统计区间[x-k,x+k]内的元素个数,想到 可以利用树状数组存元素个数(cnt)(权值数组),区间和就是元素个数,数据<=1e9,因此需要离散化a[i],a[i]+k,a[i]-k,记离散化后对应的数组为p1,p2,p3,每次区间增加下标为i的元素时,用树状数组求(p3[i],p2[i])的元素和,同时update(p1[i],1)。删除元素同理,为了防止询问时统计到自身,需要先更新再询问。

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    using namespace std;
    const int maxn=27005;
    const int maxv=maxn*3;
    typedef long long ll;
    ll res,ans[maxn];
    struct Q{
    	ll l,r,id;
    }query[maxn];
    int h[maxn],a[maxn];
    int aa[maxn*3],T[maxn*3];
    int p1[maxn],p2[maxn],p3[maxn];
    bool cmp(Q a,Q b){
    	return (h[a.l]^h[b.l])?a.l<b.l:( (h[a.l]&1)?a.r<b.r:a.r>b.r);
    }
    int lowbit(int i){
        return i &(-i);
    }
    void update(int i,int val){
        while(i<=maxv){
            T[i]+=val;
            i+=lowbit(i);
        }
    }
    int sum(int i){//求区间[1,i]内所有元素的和
        int res=0;
        while(i>0){
            res+=T[i];//从右往左累加求和
            i-=lowbit(i);
        }
        return res;
    }
    int _query(int l,int r){
    	return sum(r)-sum(l-1);
    }
    inline void insert(int x){
    	res+=_query(p3[x],p2[x]);
    	update(p1[x],1);
    }
    inline void erase(int x){
    	update(p1[x],-1);
    	res-=_query(p3[x],p2[x]);
    }
    int main(){
    	int n,m,k;
    	cin>>n>>m>>k;
    	int block=sqrt(n);
    	for(int i=0;i<=n;i++) h[i]=i/block;
    	for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    	int cnt=0;
    	//离散化
    	for(int i=1;i<=n;i++){
    		aa[++cnt]=a[i];
    		aa[++cnt]=a[i]+k;
    		aa[++cnt]=a[i]-k;
    	}
    	sort(aa+1,aa+1+cnt);
    	int size=unique(aa+1,aa+1+cnt)-(aa+1);
    	for(int i=1;i<=n;i++){
    		p1[i]=lower_bound(aa+1,aa+1+size,a[i])-aa;
    		p2[i]=lower_bound(aa+1,aa+1+size,a[i]+k)-aa;
    		p3[i]=lower_bound(aa+1,aa+1+size,a[i]-k)-aa;
    	}
    	for(int i=1;i<=m;i++){
    		scanf("%d%d",&query[i].l,&query[i].r);
    		query[i].id=i;
    	}
    	sort(query+1,query+1+m,cmp);
    	int l=1,r=0;
    	for(int i=1;i<=m;i++){
    		Q &q=query[i];
    		while(l<q.l)erase(l++);
    		while(l>q.l)insert(--l);
    		while(r>q.r)erase(r--);
    		while(r<q.r)insert(++r);
    		ans[q.id]=res;
    	}
    	for(int i=1;i<=m;i++) printf("%d
    ",ans[i]);
    }
    
  • 相关阅读:
    malloc和new的区别
    Http协议解析
    Linux基础命令-history
    Linux基础命令-last
    Linux基础命令-who
    Linux基础命令-free
    Linux基础命令-uptime
    Linux基础命令-uname
    Linux基础命令-ifconfig
    Linux基础命令-killall
  • 原文地址:https://www.cnblogs.com/ucprer/p/11347991.html
Copyright © 2020-2023  润新知