莫隊板子

Chika and Friendly Pairs

Chika gives you an integer sequence a1,a2,…,an and m tasks. For each task, you need to answer the number of "
friendly pairs" in a given interval.

friendly pair: for two integers ai and aj, if i<j and the absolute value of ai−aj is no more than a given constant integer K, then (i,j) is called a “friendly pair”.A friendly pair (i,j) in a interval [L,R] should satisfy L≤i<j≤R.

    Input
    The first line contains 3 integers n (1≤n≤27000), m (1≤m≤27000) and K (1≤K≤109), representing the number of integers in the sequence a, the number of tasks and the given constant integer. 

The second line contains n non-negative integers, representing the integers in the sequence a. Every integer of sequence a is no more than 109.

Then m lines follow, each of which contains two integers L, R (1≤L≤R≤n). The meaning is to ask the number of “friendly pairs” in the interval [L,R]。

    Output
    For each task, you need to print one line, including only 

one integer, representing the number of “friendly pairs” in the query
interval.
題意:
求任意區間裏面(a[i]-a[j])<k有多少對n個數,m次詢問。

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
#include<vector>
#define lowbits(x) x&(-x)
using namespace std;
const int N=3e4;
int sr[N],sl[N],sm[N],num[N],tr[N],cnt=0,k,sum[N],pox[N];
struct node{                                //樹狀數組維護每一個莫隊塊中序列個數,前綴數組的作用;
    int l,r,id,pot;
    bool operator <(node a)const               //預置排序;
    {
        return pot==a.pot?(pot&1?r<a.r:r>a.r):pot<a.pot;
    }
}mp[N];
inline int read()                //快讀;
{
    int x=0,f=1;char c=getchar();
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
    return x*f;
}
void update(int x, int val)             //添加元素;
{
    if(!x) return ;
    while(x<N){
        tr[x]+=val;
        x+=lowbits(x);
    }
}
int query(int x)             //查詢;
{
    int ans=0;
    while(x>0){
        ans+=tr[x];
        x-=lowbits(x);
    }
    return ans;
}
void add(int x)                  //上傳數據,計算(num-k,num+k)的數據個數;
{
    cnt+=(query(sr[x])-query(sl[x]));
    update(sm[x],1);
}
void del(int x)                //刪除元素+減去個數;
{
    update(sm[x],-1);
    cnt-=(query(sr[x])-query(sl[x]));
}
int main()
{
    int n,m,tot=1;
    register int i;              //加速運行,防止卡常;
    //scanf("%d%d%d",&n,&m,&k);
    n=read(),m=read(),k=read();
    int block=(int)sqrt(n);            //莫隊分塊,用於對輸入排序;
    for(i=1;i<=n;++i)
        num[i]=read(),pox[i]=num[i];
    for(i=0;i<m;++i){
        mp[i].l=read();
        mp[i].r=read();
        mp[i].pot=mp[i].l/block;
        mp[i].id=i;
    }
    sort(pox+1,pox+n+1);
    sort(mp,mp+m);
    for(i=2;i<=n;++i)                  //對數據離散化;
        if(pox[i]!=pox[i-1]) pox[++tot]=pox[i];
    for(i=1;i<=n;++i){
        sl[i]=lower_bound(pox+1,pox+tot+1,num[i]-k)-pox-1;  //取每一個數據的上下區間,方便後面的數據處理;
        sr[i]=upper_bound(pox+1,pox+tot+1,num[i]+k)-pox-1;
        sm[i]=lower_bound(pox+1,pox+tot+1,num[i])-pox;
    }
    int l=1,r=0;
    for(i=0;i<m;++i){
        while(r<mp[i].r) add(++r); 
        while(r>mp[i].r) del(r--);
        while(l<mp[i].l) del(l++);
        while(l>mp[i].l) add(--l);
       sum[mp[i].id]=cnt;               //記錄結果;
    }
    for(i=0;i<m;++i){
        printf("%d\n",sum[i]);
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章