ICPC Pacific Northwest Regional Contest 2019 J. Interstellar Travel 扫描求解函数

ICPC Pacific Northwest Regional Contest 2019 J. Interstellar Travel 扫描求解函数_第1张图片

大概的函数图像。

然后下面是给的题解。。懒得再叙述一遍了。

ICPC Pacific Northwest Regional Contest 2019 J. Interstellar Travel 扫描求解函数_第2张图片

我们对每个a[i]分别处理4段,每段对应一段线性区间。先预处理出a=0的值。最后从0到2*pi枚举a的取值,不停的加减影响即可。

类似于扫描线的思想。是解决这类问题的一个很棒的思想。

#include 
using namespace std;
typedef long double ld;
#define ls (o<<1)
#define rs (o<<1|1)
#define pb push_back
const ld pi= acos(-1.0);
const ld pi2= pi*2.0;
const int M = 1e6+7;
/*
int head[M],cnt;
void init(){cnt=0,memset(head,0,sizeof(head));}
struct EDGE{int to,nxt,val;}ee[M*2];
void add(int x,int y){ee[++cnt].nxt=head[x],ee[cnt].to=y,head[x]=cnt;}
*/
struct node{
	ld x,pt;
	bool operator < (const node &r)const
	{
		return xr)return ; //这一段都小于0,或l,r均越界不合法 
	if(vl>=0&&vr>=0)//这一段均大于0,都可加 
	{
		p[++sz]=node{l,s};
		p[++sz]=node{r,-s};//类似于扫描线 
	}
	else
	{
		ld x=-t/s;//a-ai 为变量 的零点
		x+=pa;//这一段的a与pa里的近,min(a,ai)可以直接用a-pa表示 
		x=max(ld(0),x);
		x=min(pi*2,x);//必须在范围内 
		if(vl>=0)
		{
			p[++sz]=node{l,s};
			p[++sz]=node{x,-s}; 
		}
		else if(vr>=0)
		{
			p[++sz]=node{x,s};
			p[++sz]=node{r,-s};
		} 
	}
}
int main()
{

  	int n;
  	cin>>n;
  	ld ans=0;
  	for(int i=1;i<=n;i++)
  	{
  		ld t,s,a;
  		scanf("%Lf%Lf%Lf",&t,&s,&a);
  		ans+=max(t-s*min(a,pi2-a),ld(0));
  		if(fabs(s)<=1e-8)continue;
  		add(a-pi2,a-pi,a-pi2,-s,t);
  		add(a-pi,a,a,s,t);
  		add(a,a+pi,a,-s,t);
  		add(a+pi,a+pi2,a+pi2,s,t);
	}
	sort(p+1,p+1+sz);
	ld mx=ans;
	ld tp=0;//当前累计斜率 

	for(int i=1;i

你可能感兴趣的:(数学——函数分析题,网络赛)