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]); }