C - Chika and Friendly Pairs HDU - 6534(之缝缝补补那些事)

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

这个题,首先可以离线,又是区间。那么离线区间我们很容易想到莫队进行操作。

所以现在的问题转换为,如何求一个数的贡献。因为莫队的操作是一个数一个数的增加。

我们需要求得是增加这个数,会增加多少个对数,删除这个数,会删除多少对数。

假设:增加一个数x。那么他能影响的是[x-k,x+k]这个区间,所以我们在增加的时候,需要计算值域[x-k,x+k]这个区间有多少个数。

删除一个数同理。

注意到,是求值域区间内有多少个数。那很自然的想到树状数组。

故代码如下:

#include"stdio.h"
#include"string.h"
#include"math.h"
#include"algorithm"
using namespace std;
#define isdigit(x) ((x) >= '0' && (x) <= '9')
inline int read() {
    int res = 0;
    char c = getchar();
    while(!isdigit(c)) c = getchar();
    while(isdigit(c)) res = (res << 1) + (res << 3) + (c ^ 48), c = getchar();
    return res;
}

const int N = 500010;
struct Node{
    int l,r,id;
}node[N];

int n,m,k;
int val[N],cnt[N],result[N];
int belong[N],Size,bnum;
int a[N]; int C[N],len;
int id[N];int now;

inline int lowbit(int x){return x & (-x);}

inline int getsum(int x){
    int res = 0;
    for(int i = x; i > 0; i -= lowbit(i)){///在这里吃了大亏,调了好久,把lowbit(i)写成了lowbit(x),哭呀
        res += C[i];
    }
    return res;
}
inline void update(int x,int v){
    for(int i = x; i <= len; i += lowbit(i)){
        C[i] += v;
    }
}

inline int cmp(Node a,Node b)
{
    return (belong[a.l] ^ belong[b.l]) ? belong[a.l] < belong[b.l] : ((belong[a.l] & 1) ? a.r < b.r : b.r < a.r);
}

inline void del(int L)
{
    int x = a[val[L]];
    int lx = x - k;int rx = x + k;
    int l = lower_bound(a + 1,a + len + 1,lx) - a;
    int r = lower_bound(a + 1,a + len + 1,rx) - a;
    if(r > len || a[r] > rx) r --;///在这里又吃了大亏,只考虑了r>len的情况。没有考虑a[r]>rx的情况。因为一开始傻傻的认为rx一定会在a数组中出现。我是智障一啊
    int q1 = getsum(r); int q2 = getsum(l - 1);
    now = now - (q1 - q2) + 1;
    update(val[L],-1);
}

inline void add(int L){
    int x = a[val[L]];
    int lx = x - k;int rx = x + k;
    int l = lower_bound(a + 1,a + len + 1,lx) - a;
    int r = lower_bound(a + 1,a + len + 1,rx) - a;
    if(r > len || a[r] > rx) r --;
    int q1 = getsum(r); int q2 = getsum(l - 1);
    now += q1 - q2;
    update(val[L],1);
}
int main()
{
    n = read(); m = read(); k = read();
    for(int i = 1; i <= n; i ++) val[i] = a[i] = read();
    sort(a + 1,a + n + 1);
    len = unique(a + 1,a + n + 1) - a - 1;
    for(int i = 1; i <= n; i ++){
        val[i] = lower_bound(a + 1,a + len + 1,val[i]) - a;
    }

    Size = sqrt(n); bnum = ceil((double)n / Size);
    for(int i = 1; i <= bnum; i ++)
        for(int j = (i - 1) * Size + 1; j <= i * Size; j ++)
           belong[j] = i;
    for(int i = 1; i <= m; i ++)
    {
        node[i].l = read(); node[i].r = read();
        node[i].id = i;
    }
    sort(node + 1,node + m + 1,cmp);

    int L = 1,R = 0;now = 0;
    for(int i = 1; i <= m; i ++)
    {
        int ql = node[i].l,qr = node[i].r;
          while(R < qr){
            ++ R;
            add(R);
        }
        while(R > qr){
           del(R); R --;
        }
        while(L < ql){
           del(L);  L ++;
        }
        while(L > ql){
            -- L;
           add(L);
        }
        result[node[i].id] = now;
    }
    for(int i = 1; i <= m; i ++)
        printf("%d\n",result[i]);
}

 

posted @ 2020-02-26 17:15  风生  阅读(160)  评论(0编辑  收藏  举报