这题要怎么优化才能不在最后两个测试点TLE?
我找出了所有能构成幽默序列的块,从这些块的任意一个数到最右端都能构成一个幽默序列,然后我保存了每个数左边和右边的块用于查找。在回答询问的时候,我先找出了两端对应的块,接着遍历中间的块,喜提TLE。(最后两个点TLE,倒数第三个点900+ms)
如果把遍历改成线段树能过吗?
附本蒟蒻代码
#include<iostream>
#include<string>
#include<iomanip>
#include<math.h>
#include<map>
using namespace std;
#define inf 0x3f3f3f3f
long long n, q;
long long num[200010];
class Pairs
{
public:
long long left;
long long right;
};
Pairs p[200010];
Pairs finding[200010];
long long pi=0;
int main()
{
cin >> n >> q;
for (long long i = 0; i < n; i++)
{
cin >> num[i];
}
long long i = 0, j, sum;
long long left, right;
while (1)
{
jumppoint1:
if (i == n)break;
left = i;
while (1)
{
if (i == n)
{
goto jumppoint1;
}
if (num[i] > 0)
{
right = i;
i++;
break;
}
i++;
}
p[pi].right = right;
j = right;
sum = 0;
while (1)
{
sum += num[j];
if (sum <= 0)
{
j++;
break;
}
if (j == left)break;
j--;
}
p[pi].left = j;
pi++;
}
long long fl = -1, fr = 0;
for (long long i = 0; i < n; i++)
{
if (fl + 1 < pi)if (p[fl + 1].left <= i)fl++;
if (fr < pi)if (p[fr].right < i)fr++;
finding[i].left = fl;
finding[i].right = fr;
}
long long l, r;
long long lp, rp;
long long sum1;
for (long long i = 0; i < q; i++)
{
sum1 = 0;
cin >> l >> r;
l--;
r--;
if (finding[l].right < pi)fl = max(l, p[finding[l].right].left);
else
{
cout << 0 << endl;
continue;
}
if (finding[r].left >= 0)fr = min(r, p[finding[r].left].right);
else
{
cout << 0 << endl;
continue;
}
lp = finding[fl].right;
rp = finding[fr].left;
for (long long j = lp; j <= rp; j++)
{
if (r < p[j].right)break;
sum1 +=
min(r, p[j].right)
-
max(l, p[j].left)
+1
;
}
cout << sum1 << endl;
}
return 0;
}