ICPC2021上海 CF103446A Strange Functions 题解
题目描述
给定 \(n\) 个函数:
\[f_i(x)=\begin{cases}
|\arctan(k_i\sec(x-a_i))|&(x\neq a_i+(k+\frac12)\pi,k\in\Z)\\
\frac\pi2&(x=a_i+(k+\frac12)\pi,k\in\Z)
\end{cases}
\]
求每个函数是否可能作为最小值出现,即 \(\forall1\le i\le n\) ,求是否存在 \(x\) ,满足 \(\forall j\neq i,f_i(x)\lt f_j(x)\) 。
数据范围
- \(1\le n\le 10^5,1\le k_i,|a_i|\le 10^5\) ,保证不存在两个完全相同的函数。
时间限制 \(\texttt{2s}\),空间限制 \(\texttt{256MB}\) 。
分析
注意到 \(\arctan x\) 为奇函数且单调递增,因此我们只需要关心 \(|k_i\sec(x-a_i)|\) 的大小关系。
如图,记 \(\angle AOD=a_i,\angle AOC_1=x,|OD|=k_i\) ,则\(|OC_1|=k_i\sec(x-a_i)\)。
特别地,如果 \(\angle COD\) 为钝角,那么交点 \(C_2\) 会落在直线 \(BE\) 上。
第 \(i\) 个函数会贡献 \(AD,BE\) 两条直线,而 \(f_i(x)\) 的最小值,就是过原点且倾角为 \(x\) 的直线(\(OC_1\))上,离原点最近的那一个。
求一遍半平面交,凸包上所有边对应的 \(f_i(x)\) 就是所有可能成为最小值的函数。
时间复杂度 \(\mathcal O(n\log n)\) 。
#include<bits/stdc++.h>
#define double long double
#define fi first
#define se second
#define mp make_pair
#define pdd pair<double,double>
using namespace std;
const int maxn=2e5+5;
const double eps=1e-10;
int a,k,m,n;
pdd p[maxn];
int q[maxn];
bool vis[maxn];
struct line
{
pdd st,ed;
int id;
}f[maxn];
pdd operator+(pdd a,pdd b)
{
return mp(a.fi+b.fi,a.se+b.se);
}
pdd operator-(pdd a,pdd b)
{
return mp(a.fi-b.fi,a.se-b.se);
}
pdd operator*(pdd a,double b)
{
return mp(a.fi*b,a.se*b);
}
int sign(double x)
{
if(fabs(x)<=eps) return 0;
return x>0?1:-1;
}
double cross(pdd a,pdd b)
{
return a.fi*b.se-a.se*b.fi;
}
double area(pdd a,pdd b,pdd c)
{
return cross(b-a,c-a);
}
double get_angle(line p)
{
return atan2(p.ed.se-p.st.se,p.ed.fi-p.st.fi);
}
bool cmp(line a,line b)
{
double x=get_angle(a),y=get_angle(b);
if(sign(x-y)) return x<y;
return sign(area(a.st,b.st,a.ed))==1;
}
pdd intersect(line a,line b)
{
double s1=area(a.st,b.st,a.ed),s2=area(a.st,a.ed,b.ed);
return b.st+(b.ed-b.st)*(s1/(s1+s2));
}
bool on_right(line a,line b,line c)
{
return sign(area(a.st,a.ed,intersect(b,c)))<=0;
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d%d",&k,&a);
f[++m]={mp(k*cos(a),k*sin(a)),mp(k*cos(a),k*sin(a))+mp(-sin(a),cos(a)),i};
f[m+1]={f[m].st*-1,f[m].ed*-1,i},m++;
}
sort(f+1,f+m+1,cmp);
int h=1,t=0;
for(int i=1;i<=m;i++)
{
if(i>=2&&!sign(get_angle(f[i])-get_angle(f[i-1]))) continue;
while(h<t&&on_right(f[i],f[q[t-1]],f[q[t]])) t--;
while(h<t&&on_right(f[i],f[q[h]],f[q[h+1]])) h++;
q[++t]=i;
}
while(h<t&&on_right(f[q[h]],f[q[t-1]],f[q[t]])) t--;
for(int i=h;i<=t;i++) vis[f[q[i]].id]=true;
for(int i=1;i<=n;i++) putchar(vis[i]+'0');
putchar('\n');
return 0;
}
本文来自博客园,作者:peiwenjun,转载请注明原文链接:https://www.cnblogs.com/peiwenjun/p/17353624.html
浙公网安备 33010602011771号