线段树求某值之前或之后与其差值不小于k的最近位置

来源:互联网 发布:驱动中国双十一数据 编辑:程序博客网 时间:2024/06/05 04:42
#include <cstdio>#include <algorithm>#include <cstring>#include <iostream>using namespace std;#define maxn 100000 + 10#define lson L, mid, rt<<1#define rson mid+1, R, rt<<1|1int n, k;int a[maxn];int ans;struct Node{    int mi, ma;}T[maxn<<2];void pushup(int rt){    int l = rt<<1, r = rt<<1|1;    T[rt].ma = max(T[l].ma, T[r].ma);    T[rt].mi = min(T[l].mi, T[r].mi);}void build(int L, int R, int rt){    if(L == R)    {        T[rt].ma = T[rt].mi = a[L];        return ;    }    int mid = (L + R) >> 1;    build(lson);    build(rson);    pushup(rt);}///注意树的节点与区间节点不要混淆void query(int l, int r, int v, int L, int R, int rt){    if(L == R)    {        if(abs(T[rt].mi - v) >= k)        {            if(ans == -1 || ans < L)                ans = L;        }        return ;    }    int mid = (L + R) >> 1;    if(r > mid)        if(abs(T[rt<<1|1].mi - v) >= k || abs(T[rt<<1|1].ma - v) >= k)        query(l, r, v, rson);    if(ans == -1 && l <= mid)        if(abs(T[rt<<1].mi - v) >= k || abs(T[rt<<1].ma - v) >= k)        query(l, r, v, lson);}int d[maxn];long long sum;int main(){    int t;    scanf("%d", &t);    while(t--)    {        sum = 1;        scanf("%d%d", &n, &k);        for(int i=1; i<=n; i++)            scanf("%d", &a[i]);        build(1, n, 1);        d[1] = 1;        for(int i=2; i<=n; i++)        {            ans = -1;            query(1, i, a[i], 1, n, 1);            if(ans == -1)               d[i] = d[i-1];            else d[i] = max(d[i-1], ans + 1);            sum += i - d[i] + 1;        }        printf("%I64d\n", sum);    }    return 0;}


阅读全文
0 0
原创粉丝点击