问题 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 ",sum); } } else { while(q--) { x=read();sum=-inf; if(hz[x+100005]) printf("%lld ",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 ",sum); } } } }