65分 TLE求助
查看原帖
65分 TLE求助
445978
kbpkbp楼主2023/10/1 21:45

这题要怎么优化才能不在最后两个测试点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;
}
2023/10/1 21:45
加载中...