【JZOJ 5390】【NOIP2017提高A组模拟9.26】逗气

Description

【JZOJ 5390】【NOIP2017提高A组模拟9.26】逗气_第1张图片

Solution

把式子的绝对值去掉就变成了一道维护直线的题面了,
这个直接用线段树即可,

像主席树那样,不下传标记,每个点都表示这一条线段,表示线段在这个区间可能会是某些坐标的最优值,
每次加入一条线段,就判断一下这条线是否在这个区间内都是由于原来的线段,否则看看是那一边比原来的优就往哪边走(可能两边都走),

询问只是一个点,所以只要看一下访问路径上的所有直线计算最大值即可,

复杂度 O(nlog(n))

Code

#include 
#include 
#include 
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fod(i,a,b) for(int i=a;i>=b;i--)
#define min(q,w) ((q)>(w)?(w):(q))
#define max(q,w) ((q)<(w)?(w):(q))
#define SU(k,b,x) ((LL)(k)*(LL)(x)+(LL)(b))
#define mxSU(k,b,l,r) (max(SU(k,b,l),SU(k,b,r)))
#define miSU(k,b,l,r) (min(SU(k,b,l),SU(k,b,r)))
using namespace std;
typedef long long LL;
const int N=200500,INF=-1e9;
int read(int &n)
{
    char ch=' ';int q=0,w=1;
    for(;(ch!='-')&&((ch<'0')||(ch>'9'));ch=getchar());
    if(ch=='-')w=-1,ch=getchar();
    for(;ch>='0' && ch<='9';ch=getchar())q=q*10+ch-48;n=q*w;return n;
}
int m,n;
LL Ans[N];
struct qwqw
{
    int k,b,i;
}a1[N],a[N];
bool PX(qwqw q,qwqw w){return q.kint l,r,k,b;
}b[N*4];
int root,b0;
void change(int l,int r,int &e,int lk,int lb)
{
    if(!e)b[e=++b0]=b[0];
    LL tl=SU(b[e].k,b[e].b,l),tr=SU(b[e].k,b[e].b,r);
    LL ll=SU(lk,lb,l),lr=SU(lk,lb,r);
    if(tl>=ll&&tr>=lr)return;
    if(tl<=ll&&tr<=lr)
    {
        b[e].k=lk,b[e].b=lb;
        return;
    }
    int t=(l+r)>>1;
    if(tlif((tr1)1)))change(t+1,r,b[e].r,lk,lb);
}
LL find(int l,int r,int e,int l1)
{
    if(b[e].k==INF&&b[e].b==INF)return -1e18;
    if(l==r)return SU(b[e].k,b[e].b,l);
    int t=(l+r)>>1;
    LL ans;
    if(l1<=t)ans=find(l,t,b[e].l,l1);
    else ans=find(t+1,r,b[e].r,l1);
    ans=max(ans,SU(b[e].k,b[e].b,l1));
    return ans;
}
int main()
{
    freopen("gas.in","r",stdin);
    freopen("gas.out","w",stdout);
    int q,w,mx=0;
    read(m),read(n);
    fo(i,1,m)read(a1[i].k),read(a1[i].b);
    fo(i,1,n)read(a[i].k),read(a[i].b),mx=max(mx,a[i].b),a[i].i=i;
    sort(a1+1,a1+1+m,PX);
    sort(a+1,a+1+n,PX);
    b[0].k=b[0].b=INF;
    a[n+1].k=a1[m+1].k=2e9;
    root=b0=0;
    for(int i=1,j=1;i<=n||j<=m;)
    {
        if(a[i].k1,mx,root,a[i].b)-(LL)a[i].k*a[i].b;
            i++;
        }else
        {
            change(1,mx,root,a1[j].k,a1[j].b);
            j++;
        }
    }
    a[0].k=a1[0].k=-2e9;
    root=b0=0;
    for(int i=n,j=m;i||j;)
    {
        if(a[i].k>a1[j].k)
        {
            LL t=find(1,mx,root,a[i].b)+(LL)a[i].k*a[i].b;
            Ans[a[i].i]=max(t,Ans[a[i].i]);
            i--;
        }else
        {
            change(1,mx,root,-a1[j].k,a1[j].b);
            j--;
        }
    }
    fo(i,1,n)printf("%lld\n",max(0,Ans[i]));
    return 0;
}

你可能感兴趣的:(【JZOJ 5390】【NOIP2017提高A组模拟9.26】逗气)