大暴力 Function

  

问题 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);
            }
             
        }
    }
}

原文地址:https://www.cnblogs.com/QTY2001/p/7632720.html