Count Triangles 队列解法

题目链接: https://codeforces.com/contest/1355/problem/C
分析: 这道题给出了3个范围,要求求出满足不退化三角形(其实就是能构成三角形啦)的个数,看数据范围5e5,肯定不是暴力(i遍历A-B,每一个i遍历B-C)能过的题。
思路: 既然暴力过不了,就优化暴力解法。取 i=A(最小边),j在B-C范围内(第二小的边),将每一个j对应的能取的三角形个数存下来(arr[j])。同时我们也得到了i=A时,所有能构成的三角形个数。
那么,当i=A+1时,相对于上一次,发现我们要计算的范围有很大一部分与上一次重叠(见下图),所以我们自然而然的想到这一次不用遍历j而直接将头去掉,尾加上就好了,那也就是队列啦。
时间复杂度: O(C - A)
Count Triangles 队列解法_第1张图片
上代码:

#include
#include
using namespace std;
int main()
{
	queue<int> que;
	long long sum=0;//结果很大int会爆掉
	int a,b,c,d;
	cin>>a>>b>>c>>d;
	for(int i=b;i<=c;i++)
	{
		int ans;		//以a,i为其中两边的三角形在C-D范围内能取的第三边的个数
		if(a+i<=c)ans=0;
		else
		{
			if(a+i>d)ans=d-c+1;
			else ans=a+i-c;
		}
		que.push(ans);
		sum+=ans;
	}
	long long res=sum;
	for(int i=a+1;i<=b;i++)
	{
		sum-=que.front();//去头
		que.pop();
		int ans=0;
		if(i+c<=c)ans=0;//加的尾巴节点
		else
		{
			if(i+c>d)ans=d-c+1;
			else ans=i;
		}
		que.push(ans);
		sum+=ans;//维护sum
		res+=sum;
	}
	cout<<res;
	return 0;
}

你可能感兴趣的:(队列,算法,队列,数据结构)