【2019湘潭邀请赛C】HDU 6534 Chika and Friendly Pairs(莫队)

    xiaoxiao2022-06-26  157

    题意

    给你一个序列,多次询问,每次让你回答一个区间中差的绝对值不超过一个给定常数K的元素对数。

    题解

    首先分析下复杂度, n , m = 2.7 ∗ 1 0 4 n,m = 2.7*10^4 n,m=2.7104,莫队复杂度 n 3 2 n^{\frac{3}{2}} n23,离散化复杂度 3 n l o g ( 3 n ) 3nlog(3n) 3nlog(3n),树状数组查询修改 l o g ( 3 n ) ∗ l o g ( 3 n ) log(3n)*log(3n) log(3n)log(3n),大概在1e8,会TLE,所以需要预处理下查询的时候上下界的复杂度,省去一个 l o g ( 3 n ) log(3n) log(3n)。 对序列中所有元素+k,-k之后再一起离散化。然后使用莫队算法对询问进行分块。在移动的过程中,用树状数组维护答案。 对于add操作,应该先更新答案再维护树状数组。不然会包括自身。 对于del操作,应该先维护树状数组再更新答案。不然会多减去自身。 树状数组的维护就是简单的二维偏序问题。

    代码

    #include <iostream> #include <algorithm> #include <cmath> using namespace std; #define FOR0(a,b) for(int i = a; i < b; ++i) #define FORE(a,b) for(int i = a; i <= b; ++i) typedef long long ll; typedef pair<int,int> pii; const int maxn = 2e5+5; template <typename _Tp> inline _Tp read(_Tp&x){ char c11=getchar(),ob=0;x=0; while(c11^'-'&&!isdigit(c11))c11=getchar();if(c11=='-')c11=getchar(),ob=1; while(isdigit(c11))x=x*10+c11-'0',c11=getchar();if(ob)x=-x;return x; } int block, ans, cnt[maxn]; int n,m,a[maxn],Ans[maxn],k, tot, b[maxn],lt[maxn], rt[maxn]; int val[maxn]; struct node { int l,r,id; }q[maxn]; bool cmp(node a, node b) { return (a.l/block)^(b.l/block)?a.l < b.l : (((a.l/block)&1)?a.r<b.r:a.r>b.r); } int getid(int x) { return lower_bound(b+1,b+tot+1,x)-b; } int lowbit(int x) { return x&(-x); } void update(int x,int v) { while(x <= tot) { val[x] += v; x += lowbit(x); } } int query(int x) { int ret = 0; while(x) { ret += val[x]; x -= lowbit(x); } return ret; } void add(int x) { ans += query(rt[x])-query(lt[x]); // cout <<x <<": " << a[x] << " " <<lt[x] <<" " << rt[x] <<" "<< ans << endl; update(a[x],1); } void del(int x) { update(a[x],-1); ans -= query(rt[x])-query(lt[x]); } int main() { read(n); read(m); read(k); for(int i = 1; i <= n; ++i) read(a[i]); for(int i = 1; i <= m; ++i) { read(q[i].l); read(q[i].r); q[i].id = i; } block = n/sqrt(m*2/3); tot = 1; for(int i = 1; i <= n; ++i) { b[tot] = a[i], b[tot+1] = a[i]+k, b[tot+2] = a[i]-k-1; tot += 3; } sort(b+1,b+tot); tot = unique(b+1,b+tot)-b-1; sort(q+1,q+m+1,cmp); for(int i = 1; i <= n; ++i) { lt[i] = getid(a[i]-k-1); rt[i] = getid(a[i]+k); a[i] = getid(a[i]); // cout << i <<": " << lt[i] <<" " << rt[i] <<" " << a[i] << endl; } int l = 1,r = 0; for(int i = 1; i <= m; ++i) { int ql = q[i].l, qr = q[i].r; // cout << ql << " " << qr << endl; while(r < qr) add(++r); while(r > qr) del(r--); while(l < ql) del(l++); while(l > ql) add(--l); Ans[q[i].id] = ans; } for(int i = 1; i <= m; ++i) printf("%d\n", Ans[i]); return 0; }

    最新回复(0)