Loading

NOIP 模拟 $98\; \rm 序列$

题解 \(by\;zj\varphi\)

因为询问的区间要经过点 \(p\),所以可以拆成 \([l,p]\)\([p+1,n]\) 两端。

对于前一段,相当于是求 \(suma_p-k\times sumb_p-\min(suma_l-k\times sumb_l)\),就是求

\[\max(k\times sumb_l-suma_l)(l\in [0,p-1]) \]

那么将每个前缀和看成一个斜率为 \(sumb\),截距为 \(suma\) 的直线。

将所有询问离线,从左往右依次加入所有直线,同时维护询问,后半段同理。

Code
#include<bits/stdc++.h>
#define ri signed
#define pd(i) ++i
#define bq(i) --i
#define func(x) std::function<x>
namespace IO{
    char buf[1<<21],*p1=buf,*p2=buf;
    #define gc() p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?(-1):*p1++
    #define dg1(x) std::cerr << #x"=" << x << ' '
    #define dg2(x) std::cerr << #x"=" << x << std::endl
    #define Dg(x) assert(x)
    struct nanfeng_stream{
        template<typename T>inline nanfeng_stream &operator>>(T &x) {
            bool f=false;x=0;char ch=gc();
            while(!isdigit(ch)) f|=ch=='-',ch=gc();
            while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=gc();
            return x=f?-x:x,*this;
        }
    }cin;
}
using IO::cin;
namespace nanfeng{
    #define FI FILE *IN
    #define FO FILE *OUT
    template<typename T>inline T cmax(T x,T y) {return x>y?x:y;}
    template<typename T>inline T cmin(T x,T y) {return x>y?y:x;}
    using ll=long long;
    static const int N=1e6+7,bs=1e6+1;
    int a,b,n,m,mk;
    ll sma[N],smb[N],ans[N];
    struct Que{int p,k,id;}que[N];
    struct stra{ll k,b;}tmp;
    auto calc=[](stra a,int x) {return a.k*x+a.b;};
    auto cr=[](stra a,stra b) {return (1.0*(a.b-b.b))/(b.k-a.k);};
    struct Seg{
        #define ls(x) (x<<1)
        #define rs(x) (x<<1|1)
        struct segmenttree{stra x;bool f;}T[N<<4];
        void update(int x,int l,int r) {
            if (!T[x].f) return T[x].f=true,T[x].x=tmp,void();
            ll yl=calc(T[x].x,l-bs),yr=calc(T[x].x,r-bs),yyl=calc(tmp,l-bs),yyr=calc(tmp,r-bs);
            if (yyl>=yl&&yyr>=yr) return T[x].x=tmp,void();
            if (yyl<yl&&yyr<yr) return;
            double p=cr(T[x].x,tmp)+bs;
            int mid=(l+r)>>1;
            if (yyl>=yl) {
                if (p<=1.0*mid) update(ls(x),l,mid);
                else {
                    stra tpm=tmp;
                    tmp=T[x].x;
                    T[x].x=tpm;
                    update(rs(x),mid+1,r);
                }
            } else {
                if (p>1.0*mid) update(rs(x),mid+1,r);
                else {
                    stra tpm=tmp;
                    tmp=T[x].x;
                    T[x].x=tpm;
                    update(ls(x),l,mid);
                }
            }
        }
        ll query(int x,int nx,int l,int r) {
            ll res=LONG_LONG_MIN;
            if (T[x].f) res=calc(T[x].x,nx-bs);
            if (l==r) return res;
            int mid=(l+r)>>1;
            if (nx<=mid) res=cmax(res,query(ls(x),nx,l,mid));
            else res=cmax(res,query(rs(x),nx,mid+1,r));
            return res;
        };
        void clear(int x,int l,int r) {
            T[x].f=false;
            if (l==r) return;
            int mid=(l+r)>>1;
            clear(ls(x),l,mid),clear(rs(x),mid+1,r);
        }
    }T;
    inline int main() {
        FI=freopen("seq.in","r",stdin);
        FO=freopen("seq.out","w",stdout);
        cin >> n >> m;
        for (ri i(1);i<=n;pd(i))
            cin >> a >> b,sma[i]=sma[i-1]+a,smb[i]=smb[i-1]+b;
        for (ri i(1);i<=m;pd(i)) {
            cin >> que[i].p >> que[i].k;
            que[i].id=i;
            mk=cmax(mk,que[i].k);
        }
        const int lim=mk+bs;
        std::sort(que+1,que+m+1,[](const Que &q1,const Que &q2) {return q1.p<q2.p;});
        tmp={0,0};
        T.update(1,1,lim);
        int pnt=1;
        for (ri i(1);i<=m;pd(i)) {
            while(pnt<que[i].p) tmp={smb[pnt],-sma[pnt]},T.update(1,1,lim),++pnt;
            ans[que[i].id]=T.query(1,que[i].k+bs,1,lim);
        }
        T.clear(1,1,lim);
        pnt=n;
        for (ri i(m);i;bq(i)) {
            while(pnt>=que[i].p) tmp={-smb[pnt],sma[pnt]},T.update(1,1,lim),--pnt;
            ans[que[i].id]+=T.query(1,que[i].k+bs,1,lim);
        }
        for (ri i(1);i<=m;pd(i)) printf("%lld\n",ans[i]);
        return 0;
    }
}
int main() {return nanfeng::main();}
posted @ 2021-11-14 20:17  ナンカエデ  阅读(41)  评论(0编辑  收藏  举报