题解 序列
发现那个 \(k\) 每次都在变着实很烦
于是将 \(k\) 看做变量 \(x\),将 \(\sum b\) 看做 \(k\),将 \(\sum a\) 看做 \(b\)
于是每个决策点都可以表示为一条 \(kx+b\) 的直线,李超树维护即可
- 李超树维护直线(不是线段)是 \(O(nlogn)\) 的
Code:
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f3f3f3f3f
#define N 1000010
#define ll long long
#define fir first
#define sec second
#define make make_pair
#define pb push_back
//#define int long long
char buf[1<<21], *p1=buf, *p2=buf;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf, 1, 1<<21, stdin)), p1==p2?EOF:*p1++)
inline int read() {
int ans=0, f=1; char c=getchar();
while (!isdigit(c)) {if (c=='-') f=-f; c=getchar();}
while (isdigit(c)) {ans=(ans<<3)+(ans<<1)+(c^48); c=getchar();}
return ans*f;
}
int n, m;
ll a[N], b[N];
#if 0
namespace force{
ll calc(int l, int r, ll k) {
ll suma=0, sumb=0;
for (int i=l; i<=r; ++i) suma+=a[i], sumb+=b[i];
return suma-k*sumb;
}
void solve() {
ll k, ans;
for (int i=1,p; i<=m; ++i) {
p=read(); k=read(); ans=-INF;
for (int l=1; l<=p; ++l) for (int r=p; r<=n; ++r) ans=max(ans, calc(l, r, k));
printf("%lld\n", ans);
}
exit(0);
}
}
namespace task1{
ll ans[N], prea[N], preb[N], sufa[N], sufb[N];
vector<pair<int, int>> que[N];
void solve() {
for (int i=1; i<=n; ++i) prea[i]=prea[i-1]+a[i], preb[i]=preb[i-1]+b[i];
for (int i=n; i; --i) sufa[i]=sufa[i+1]+a[i], sufb[i]=sufb[i+1]+b[i];
for (int i=1; i<=m; ++i) {
int p=read(), k=read();
que[p].pb(make(k, i));
}
for (int i=1; i<=n; ++i) for (auto it:que[i]) {
ll k=it.fir, tem;
tem=-k*sufb[i]+sufa[i];
for (int j=1; j<=i; ++j) tem=max(tem, -k*sufb[j]+sufa[j]);
ans[it.sec]+=tem-(-k*sufb[i]+sufa[i]);
tem=-k*preb[i]+prea[i];
for (int j=i; j<=n; ++j) tem=max(tem, -k*preb[j]+prea[j]);
ans[it.sec]+=tem-(-k*preb[i]+prea[i]);
ans[it.sec]+=a[i]-k*b[i];
}
for (int i=1; i<=m; ++i) printf("%lld\n", ans[i]);
exit(0);
}
}
#endif
namespace task2{
ll ans[N], prea[N], preb[N], sufa[N], sufb[N];
vector<pair<int, int>> que[N];
struct line{
ll k, b;
line(){}
line(ll x, ll y):k(x),b(y){}
inline ll at(ll x) {return k*x+b;}
};
struct lichao{
line dat[N<<3];
// int tl[N<<3], tr[N<<3];
bool noline[N<<3];
// bitset<N<<3> noline;
// #define tl(p) tl[p]
// #define tr(p) tr[p]
#define noline(p) noline[p]
#define dat(p) dat[p]
void build(int p, int l, int r) {
// cout<<"build: "<<p<<' '<<l<<' '<<r<<endl;
// tl(p)=l; tr(p)=r;
noline(p)=1; dat(p)=line(0, 0);
if (l==r) return ;
int mid=floor((l+r)/2.0L);
build(p<<1, l, mid);
build(p<<1|1, mid+1, r);
}
void upd(int p, int tl, int tr, const int& l, const int& r, line val) {
// cout<<"upd: "<<p<<' '<<tl(p)<<' '<<tr(p)<<' '<<l<<' '<<r<<' '<<val.k<<' '<<val.b<<endl;
int mid=floor((tl+tr)/2.0);
if (l<=tl&&r>=tr) {
if (noline(p)) {dat(p)=val; noline(p)=0; return ;}
if (tl==tr) {
if (val.at(tl)>dat(p).at(tl)) dat(p)=val;
return ;
}
if (dat(p).k==val.k) dat(p)=dat(p).b>val.b?dat(p):val;
else if (dat(p).k>val.k) {
if (dat(p).at(mid)>=val.at(mid)) {
// upd(p<<1, l, r, dat(p));
upd(p<<1, tl, mid, l, r, val);
}
else {
// upd(p<<1|1, l, r, val);
upd(p<<1|1, mid+1, tr, l, r, dat(p));
dat(p)=val;
}
}
else {
if (dat(p).at(mid)>=val.at(mid)) {
// upd(p<<1|1, l, r, dat(p));
upd(p<<1|1, mid+1, tr, l, r, val);
}
else {
upd(p<<1, tl, mid, l, r, dat(p));
// upd(p<<1, l, r, val);
dat(p)=val;
}
}
return ;
}
if (l<=mid) upd(p<<1, tl, mid, l, r, val);
if (r>mid) upd(p<<1|1, mid+1, tr, l, r, val);
}
ll query(int p, int tl, int tr, const ll pos) {
// cout<<"query: "<<p<<' '<<pos<<' '<<dat(p).k<<' '<<dat(p).b<<' '<<noline(p)<<endl;
ll dlt=noline(p)?-INF:dat(p).at(pos);
if (tl==tr) return dlt;
int mid=floor((tl+tr)/2.0L);
if (pos<=mid) return max(query(p<<1, tl, mid, pos), dlt);
else return max(query(p<<1|1, mid+1, tr, pos), dlt);
}
}tr1;
void solve() {
// cout<<double(sizeof(tr1))/1000/1000<<endl; return ;
ll lim=1000010;
tr1.build(1, -lim, lim);
for (int i=1; i<=n; ++i) prea[i]=prea[i-1]+a[i], preb[i]=preb[i-1]+b[i];
for (int i=n; i; --i) sufa[i]=sufa[i+1]+a[i], sufb[i]=sufb[i+1]+b[i];
for (int i=1; i<=m; ++i) {
int p=read(), k=read();
que[p].pb(make(k, i));
}
for (int i=1; i<=n; ++i) {
// cout<<"i: "<<i<<endl;
tr1.upd(1, -lim, lim, -lim, lim, line(sufb[i], sufa[i]));
for (auto it:que[i]) {
ll k=it.fir, tem=tr1.query(1, -lim, lim, -k);
// cout<<"tem: "<<tem<<endl;
ans[it.sec]+=tem-(-k*sufb[i]+sufa[i]);
}
}
tr1.build(1, -lim, lim);
for (int i=n; i; --i) {
// cout<<"i: "<<i<<endl;
tr1.upd(1, -lim, lim, -lim, lim, line(preb[i], prea[i]));
for (auto it:que[i]) {
ll k=it.fir, tem=tr1.query(1, -lim, lim, -k);
// cout<<"tem: "<<tem<<endl;
ans[it.sec]+=tem-(-k*preb[i]+prea[i]);
}
}
for (int i=1; i<=n; ++i) for (auto it:que[i]) {
ans[it.sec]+=a[i]-it.fir*b[i];
}
for (int i=1; i<=m; ++i) printf("%lld\n", ans[i]);
exit(0);
}
}
signed main()
{
freopen("seq.in", "r", stdin);
freopen("seq.out", "w", stdout);
n=read(); m=read();
for (int i=1; i<=n; ++i) a[i]=read(), b[i]=read();
// force::solve();
// task1::solve();
task2::solve();
return 0;
}