问题 C: Function
时间限制: 2 Sec 内存限制: 512 MB提交: 76 解决: 49
[ 提交][ 状态][ 讨论版]
题目描述

正解是估值线段树。。我不会。。。QAQ,我只会打暴力,而且这道题成功虐了出题人智商,优化一下暴力就能A。 思路就是求解多于范围。所以记录每个访问点的值,如果再访问,直接输出就行。注意会卡常数。
我联考时还是打了点有思维含量的东西的。就是3~6这三个点,只是一次函数,单调的。求每个交点,更新每条直线是总体最大值的区间。两个优化。1,左端点大于右端点过掉。2,交点不一定是整数,所以要调整交点的值。(这个貌似不是优化)记录询问区间里每个点对应的最大值函数的下标。。
联考时被卡常了QAQAQAQ
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#define ll long long
#define inf 1000000000
using namespace std;
inline ll read()
{
ll x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return x*f;
}
struct qj
{
int l,r;
} f[1005];
int n,q,p=0,v[1005];
ll a[1005],b[1005],c[1005];
ll hz[200204],cun[200205];
inline ll get(int i,int x)
{
return a[i]*x*x+b[i]*x+c[i];
}
void init()//唯一不是暴力的地方。。。
{
for(int i=1;i<=n;i++){f[i].l=-100000;f[i].r=100000;}
for(int i=1;i<=n;i++)
for(int j=i+1;j<=n;j++)
if(!v[i]&&!v[j])
{
if(b[i]==b[j])
{
if(c[i]>=c[j])v[j]=1;
else v[i]=1;
continue;
}
if(b[i]>b[j])
{
int x=(c[j]-c[i])/(b[i]-b[j]);
int a1=get(i,x),a2=get(j,x);
if(a1==a2)
{
if(x>f[i].l)f[i].l=x;if(x>f[i].r)v[i]=1;
if(f[j].r>x)f[j].r=x;if(x<f[j].l)v[j]=1;
}
else
{
int x1=x,x2=x;
if(a1<a2)x1++;
else x2--;
if(x1>f[i].l)f[i].l=x1;if(x1>f[i].r)v[i]=1;
if(f[j].r>x2)f[j].r=x2;if(x2<f[j].l)v[j]=1;
}
}
else
{
int x=(c[j]-c[i])/(b[i]-b[j]);
int a1=get(i,x),a2=get(j,x);
if(a1==a2)
{
if(x>f[j].l)f[j].l=x;if(x>f[j].r)v[j]=1;
if(f[i].r>x)f[i].r=x;if(x<f[i].l)v[i]=1;
}
else
{
int x1=x,x2=x;
if(a1<a2)x1--;
else x2++;
if(x2>f[j].l)f[j].l=x2;if(x2>f[j].r)v[j]=1;
if(f[i].r>x1)f[i].r=x1;if(x1<f[i].l)v[i]=1;
}
}
}
for(int i=1;i<=n;i++)
if(!v[i])
{
for(int j=f[i].l;j<=f[i].r;j++)
cun[j+100005]=i;
}
}
int main()
{
//freopen("function.in","r",stdin);
//freopen("function.out","w",stdout);
n=read();q=read();
for(int i=1;i<=n;i++)
{
a[i]=read();if(a[i]!=0)p=1;
b[i]=read();
c[i]=read();
}
int x;ll sum=-inf;
if(!p)
{
init();
while(q--)
{
x=read();
int i=cun[x+100005];
sum=a[i]*x*x+b[i]*x+c[i];
printf("%lld\n",sum);
}
}
else
{
while(q--)
{
x=read();sum=-inf;
if(hz[x+100005])
printf("%lld\n",hz[x+100005]);
else
{
for(int i=1;i<=n;i++)
{
ll k=a[i]*x*x+b[i]*x+c[i];
if(sum<k)sum=k;
}
hz[x+100005]=sum;
printf("%lld\n",sum);
}
}
}
}