HDU - 6534 Chika and Friendly Pairs

这个题其实也是很简单的莫队,题目要求是给一个序列,询问l-r区间内部,找到有多少对答案满足 i < j 并且

| a[ i ] -a[ j ] | <=k 也就是有多少对,满足差值小于k的个数。

把这个式子展开,其实就是-k<= a[ i ] -a [ j ] <= k 也就是  a[ j ] -k <= a[ i ] <= a[ j ] + k,也就是说,对于某个 j 位置,我们需要在询问的区间内,找到 i < j 并且在[ a[j] -k ,a[j] +k ] 范围中的数的个数,这个其实可以通过树状数组区间查询即可。

但是对于k来说,太大了,树状数组也开不下,所以我们要进行离散化,把a[i],a[i]+k,a[i]-k位置存下来即可(老套路了)保证每个位置都能找得到,然后区间查询即可,然后每次算贡献即可。

#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<string.h>
using namespace std;
const int maxx = 2e5+6;
int block;
int a[maxx];
std::vector<int>vx;
int sum[maxx];
int ans[maxx];
int num;
int n,m,k;
struct node{
  int l,r;
  int id;
  friend bool operator < (const node &a,const node &b){
      if(a.l/block==b.l/block){
          return a.r<b.r;
      }
      return a.l/block<b.l/block;
  }
}q[maxx];
int low[maxx];
int up[maxx];
int p[maxx];
int lowbit(int x){
  return x&(-x);
}
void add(int x,int w){
   for(int i=x;i<=3*n;i+=lowbit(i)){
     sum[i]+=w;
   }
   return ;
}
int getsum(int x){
   int s=0;
   for(int i=x;i;i-=lowbit(i)){
       s+=sum[i];
   }
   return s;
}
void add(int x){
   num+=getsum(up[x])-getsum(low[x]-1);
   add(p[x],1);
}
void del(int x){
   add(p[x],-1);
   num-=getsum(up[x])-getsum(low[x]-1);
}
int main(){
  while(~scanf("%d%d%d",&n,&m,&k)){
     block=sqrt(n);
     memset(sum,0,sizeof(sum));
     memset(ans,0,sizeof(ans));
     vx.clear();
     ///绝对值小于等于K
     for (int i=1;i<=n;i++){
        scanf("%d",&a[i]);
        vx.push_back(a[i]);
        vx.push_back(a[i]+k);
        vx.push_back(a[i]-k);
     }
     num=0;
     sort(vx.begin(),vx.end());
     vx.erase(unique(vx.begin(),vx.end()),vx.end());
     int sz=vx.size();
     for(int i=1;i<=n;i++){
        p[i]=lower_bound(vx.begin(),vx.end(),a[i])-vx.begin()+1;
        low[i]=lower_bound(vx.begin(),vx.end(),a[i]-k)-vx.begin()+1;
        up[i]=lower_bound(vx.begin(),vx.end(),a[i]+k)-vx.begin()+1;
     }
     for(int i=1;i<=m;i++){
       scanf("%d%d",&q[i].l,&q[i].r);
       q[i].id=i;
     }
     sort(q+1,q+1+m);
     int l=1,r=0;
     num=0;
     for(int i=1;i<=m;i++){
        while(l<q[i].l)del(l),l++;
      //  cout<<num<<" ";
        while(l>q[i].l)l--,add(l);
      //  cout<<num<<" ";
        while(r<q[i].r)r++,add(r);
       // cout<<num<<" ";
        while(r>q[i].r)del(r),r--;
      //  cout<<num<<" "<<endl;
        ans[q[i].id]=num;
     }
    for(int i=1;i<=m;i++){
        printf("%d\n",ans[i]);
    }
  }
  return 0;
}

原文地址:https://www.cnblogs.com/bluefly-hrbust/p/11530842.html

时间: 2024-11-09 09:20:45

HDU - 6534 Chika and Friendly Pairs的相关文章

Chika and Friendly Pairs(莫队+树状数组+离散化+预处理上下界)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6534 Chika and Friendly Pairs Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 524288/524288 K (Java/Others)Total Submission(s): 160    Accepted Submission(s): 52 Problem Description Chika gives y

Chika and Friendly Pairs(莫队+离散化+树状数组)

Chika and Friendly Pairs Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 524288/524288 K (Java/Others)Total Submission(s): 1164    Accepted Submission(s): 421 Problem Description Chika gives you an integer sequence a1,a2,…,an and m tasks. For

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

题意:给你一个数组,对于第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,每次区间增加下标为

莫队专题

https://blog.csdn.net/qq_41552508/article/details/100556943附上学习连接 以防万一还是搬出来吧 一.适用问题 莫队算法是一种离线算法,用分块去优化暴力,不包含修改的话,复杂度为 O(nn−−√+mn−−√) O(n\sqrt n+m\sqrt n)O(n n ? +m n ? ),n nn 为序列长度,m mm 为操作总数. 二.算法实现 莫队本质上就是用分块去优化暴力的离线算法,将总复杂度降到 O(nn−−√) O(n\sqrt n)O

AtCoder Regular Contest 092 2D Plane 2N Points AtCoder - 3942 (匈牙利算法)

Problem Statement On a two-dimensional plane, there are N red points and N blue points. The coordinates of the i-th red point are (ai,bi), and the coordinates of the i-th blue point are (ci,di). A red point and a blue point can form a friendly pair w

(点的配对)二分图最大匹配

传送门:https://abc091.contest.atcoder.jp/tasks/arc092_a?lang=en 题目:On a two-dimensional plane, there are N red points and N blue points. The coordinates of the i-th red point are (ai, bi), and the coordinates of the i-th blue point are (c_i, d_i). A red

HDU 5178 pairs 二分

传送门:http://acm.hdu.edu.cn/showproblem.php?pid=5178 pairs Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 320    Accepted Submission(s): 143 Problem Description John has n points on the X axis,

hdu 4750 Count The Pairs 最小生成树

题意就是给出一个f值,然后假如两个点u,v间的所有路径上的最大边中的最小值大于f,那么这个点对是合法的,对于每个询问f,输出有多少个合法点对. 最大边最小就是最小瓶颈路,即最小生成树上的路径.一个简单的想法就是求出最小生成树后,n次dfs求出任意两点间的最大边,然后对于每个询问再查找一遍,可是时间复杂度太高.再想想的话会发现,两点间生成树上的最大边就是在克鲁斯卡尔的过程中使得他们第一次联通的那条边,所以,每加进一条边,以该边为最大边的点对就是他连接的两个集合的点对. #include <cstd

HDU 5178 Pairs

pairs Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 96    Accepted Submission(s): 38 Problem Description John has n points on the X axis, and their coordinates are (x[i],0),(i=0,1,2,…,n−1). He