Assignment
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 3192 Accepted Submission(s): 1468
28
solution:
我們可以枚舉左端點,然後用ST表和尺取來找出最右邊的端點。
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn = 1e5 + 200;
int dpmax[maxn][20], dpmin[maxn][20],mm[maxn];
int a[maxn],n;
void init()
{
mm[0] = -1;
for (int i = 1; i <= n; i++)
{
mm[i] = ((i&(i - 1)) == 0) ? mm[i - 1] + 1 : mm[i - 1];
dpmax[i][0] = dpmin[i][0] = a[i];
}
for (int j = 1; j <= mm[n]; j++)
for (int i = 1; i + (1 << j) - 1 <= n; i++)
{
dpmax[i][j] = max(dpmax[i][j - 1], dpmax[i + (1 << (j - 1))][j - 1]);
dpmin[i][j] = min(dpmin[i][j - 1], dpmin[i + (1 << (j - 1))][j - 1]);
}
}
int rmq(int x, int y)
{
int k = mm[y - x + 1];
return max(dpmax[x][k], dpmax[y - (1 << k) + 1][k]) - min(dpmin[x][k], dpmin[y - (1 << k) + 1][k]);
}
int main()
{
int k, t;
scanf("%d", &t);
while (t--)
{
scanf("%d%d", &n, &k);
for (int i = 1; i <= n; i++)
scanf("%d", &a[i]);
init();
long long ans = 0;
int l = 1;
for (int i = 1; i <= n; i++)
{
while (rmq(l, i) >= k&&l < i)l++;
ans += (i - l + 1);
}
printf("%I64d\n", ans);
}
return 0;
}