luoguP5073 [Ynoi Easy Round 2015] 世上最幸福的女孩 题解
准备写分块,被同学喊来写末日三问,这是弱化版。
考虑处理这个问题,对于正常的区间最大子段和,我们显然可以直接线段树去维护,这道题目多了一个区间加,我们的最大子段和就和长度有了关系,对于每一个节点维护凸包,对于左子树的右儿子和右子树的左儿子做闵可夫斯基和就可以了,对于时间只有\(O(n\log n)\),我们可以提前按全局增加的数值排序,然后凸包直接用指针扫过去,对于空间只有\(O(n)\),我们可以考虑在建线段树的时候动态处理答案,并且把询问用类似于整体二分的写法下方(就是有序的序列不断地分裂,或者用归并线性合并两个有序序列。)
#include <bits/stdc++.h>
#define lll long long
#define fw fwrite(obuf,p3-obuf,1,stdout)
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin),p1==p2)?EOF:*p1++)
#define putchar(x) (p3-obuf<1<<20?(*p3++=(x)):(fw,p3=obuf,*p3++=(x)))
using namespace std;
char buf[1<<20],obuf[1<<20],*p1=buf,*p2=buf,*p3=obuf,str[20<<2];
lll read(){
lll x=0,f=1;
char ch=getchar();
while(!isdigit(ch))ch=='-'&&(f=-1),ch=getchar();
while(isdigit(ch))x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
return x*f;
}
template<typename T>
void write(T x,char sf='\n'){
if(x<0)putchar('-'),x=~x+1;
lll top=0;
do str[top++]=x%10,x/=10;while(x);
while(top)putchar(str[--top]+48);
if(sf^'#')putchar(sf);
}
inline lll max(lll a,lll b){
return a>b?a:b;
}
constexpr lll maxn=6e5+10;
constexpr lll INF=0x3f3f3f3f3f3f3f3fll,IINF=0xc0c0c0c0c0c0c0c0ll;
lll tg,ans[maxn],pre[maxn],val1,val2,tp,V[maxn];
int n,m,op,x,y,ttp,a[maxn],L,R,ll,rr,tt[maxn],lin[maxn];
pair<int,lll>st[maxn<<1];
vector<pair<int,lll> >f[210],g[210],h[210];
struct edge{
int l;
int r;
lll k;
int id;
}wen[maxn];
inline bool cmp(edge q,edge w){
return q.k<w.k;
}
inline lll val(lll q,pair<int,lll> w){
return q*w.first+w.second;
}
inline void querys(int id,int idd){
int nowf=0,nowg=0,nowh=0;
for(int i=1;i<=id;i++){
while(nowf<f[idd].size()-1&&val(wen[tt[i]].k,f[idd][nowf])<val(wen[tt[i]].k,f[idd][nowf+1])){
nowf++;
}
while(nowg<g[idd].size()-1&&val(wen[tt[i]].k,g[idd][nowg])<val(wen[tt[i]].k,g[idd][nowg+1])){
nowg++;
}
while(nowh<h[idd].size()-1&&val(wen[tt[i]].k,h[idd][nowh])<val(wen[tt[i]].k,h[idd][nowh+1])){
nowh++;
}
ans[wen[tt[i]].id]=max(ans[wen[tt[i]].id],val(wen[tt[i]].k,f[idd][nowf])+pre[wen[tt[i]].id]);
ans[wen[tt[i]].id]=max(ans[wen[tt[i]].id],val(wen[tt[i]].k,h[idd][nowh]));
pre[wen[tt[i]].id]=max(pre[wen[tt[i]].id]+val(wen[tt[i]].k,g[idd][g[idd].size()-1]),val(wen[tt[i]].k,g[idd][nowg]));
}
return;
}
inline void clean(int id){
vector<pair<int,lll> >().swap(f[id]);
vector<pair<int,lll> >().swap(g[id]);
vector<pair<int,lll> >().swap(h[id]);
return;
}
inline void pai(vector<pair<int,lll> >&q){
for(int i=1;i<=tp;i++){
while(q.size()&&q.back().first==st[i].first&&q.back().second<=st[i].second){
q.pop_back();
}
while(q.size()>1&&(q[q.size()-1].second-q[q.size()-2].second)*(q[q.size()-1].first-st[i].first)>
(q[q.size()-2].first-q[q.size()-1].first)*(st[i].second-q[q.size()-1].second)){
q.pop_back();
}
q.emplace_back(st[i]);
}
tp=0;
return;
}
int cmp1(int q,int w){
if(wen[q].k!=wen[w].k){
return wen[q].k<wen[w].k;
}
return wen[q].id<wen[w].id;
}
inline void get(int l,int r,int qw,int wq){
if(l==r){
f[qw].emplace_back(1,a[l]);
g[qw].emplace_back(1,a[l]);
h[qw].emplace_back(1,a[l]);
querys(wq,qw);
return;
}
int mid=(l+r)>>1;
int ll3=0,ll4=0,ll5=0;
L=0,R=wq+1;
for(lll i=1;i<=wq;i++){
if(wen[tt[i]].l>l||r>wen[tt[i]].r){
L++;
lin[L]=tt[i];
}
else{
R--;
lin[R]=tt[i];
}
}
memcpy(tt,lin,(wq+1)<<2);
ll5=wq-R+1;
wq=L;
L=0,R=wq+1;
for(lll i=1;i<=wq;i++){
if((wen[tt[i]].l>l||r>wen[tt[i]].r)&&wen[tt[i]].l<=mid){
L++;
lin[L]=tt[i];
}
else{
R--;
lin[R]=tt[i];
}
}
memcpy(tt,lin,(wq+1)<<2);
ll3=L;
get(l,mid,qw+1,L);
memcpy(lin,tt,(wq+1)<<2);
L=1,R=wq,ll4=0;
while(L<=ll3||R>ll3){
if(R<=ll3||(L<=ll3&&lin[L]<lin[R])){
tt[++ll4]=lin[L];
L++;
}
else{
tt[++ll4]=lin[R];
R--;
}
}
L=0,R=wq+1;
for(lll i=1;i<=wq;i++){
if((wen[tt[i]].l>l||r>wen[tt[i]].r)&&wen[tt[i]].r>mid){
L++;
lin[L]=tt[i];
}
else{
R--;
lin[R]=tt[i];
}
}
memcpy(tt,lin,(wq+1)<<2);
ll3=L;
get(mid+1,r,qw+2,L);
memcpy(lin,tt,(wq+1)<<2);
L=1,R=wq,ll4=0;
while(L<=ll3||R>ll3){
if(R<=ll3||(L<=ll3&&lin[L]<lin[R])){
tt[++ll4]=lin[L];
L++;
}
else{
tt[++ll4]=lin[R];
R--;
}
}
reverse(tt+1,tt+wq+1);
lll ll1=0,ll2=0;
ll1=f[qw+1][f[qw+1].size()-1].first;
ll2=f[qw+1][f[qw+1].size()-1].second;
for(auto x:f[qw+1]) f[qw].emplace_back(x);
for(auto x:f[qw+2]) st[++tp]={ll1+x.first,ll2+x.second};
pai(f[qw]);
ll1=g[qw+2][g[qw+2].size()-1].first;
ll2=g[qw+2][g[qw+2].size()-1].second;
for(auto x:g[qw+2]) g[qw].emplace_back(x);
for(auto x:g[qw+1]) st[++tp]={ll1+x.first,ll2+x.second};
pai(g[qw]);
L=1,R=1,val1=g[qw+1][0].second,val2=f[qw+2][0].second,ll=g[qw+1][0].first,rr=f[qw+2][0].first;
st[++tp]={ll+rr,val1+val2};
while(L<g[qw+1].size()||R<f[qw+2].size()){
if(R==f[qw+2].size()||(L<g[qw+1].size()&&(g[qw+1][L].second-val1)*(f[qw+2][R].first-rr)>(f[qw+2][R].second-val2)*(g[qw+1][L].first-ll))){
val1=g[qw+1][L].second;
ll=g[qw+1][L].first;
L++;
}
else{
val2=f[qw+2][R].second;
rr=f[qw+2][R].first;
R++;
}
st[++tp]={ll+rr,val1+val2};
}
for(auto x:h[qw+1]) st[++tp]=x;
for(auto x:h[qw+2]) st[++tp]=x;
memset(V,0xc0,(r-l+2)<<3);
for(lll i=1;i<=tp;i++){
V[st[i].first]=max(V[st[i].first],st[i].second);
}
tp=0;
for(lll i=1;i<=r-l+1;i++){
if(V[i]!=IINF){
st[++tp]={i,V[i]};
}
}
pai(h[qw]);
clean(qw+1);
clean(qw+2);
wq+=ll5;
reverse(tt+1,tt+wq+1);
reverse(tt+ll5+1,tt+wq+1);
querys(ll5,qw);
memcpy(lin,tt,(wq+1)<<2);
ll3=ll5;
L=1,R=wq,ll4=0;
while(L<=ll3||R>ll3){
if(R<=ll3||(L<=ll3&&lin[L]<lin[R])){
tt[++ll4]=lin[L];
L++;
}
else{
tt[++ll4]=lin[R];
R--;
}
}
return;
}
signed main(){
n=read(),m=read();
for(int i=1;i<=n;i++){
a[i]=read();
}
for(int i=1;i<=m;i++){
op=read();
if(op==1){
x=read();
tg+=x;
}
else{
x=read(),y=read();
wen[++ttp]={x,y,tg,ttp};
}
}
sort(wen+1,wen+1+ttp,cmp);
for(int i=1;i<=ttp;i++){
tt[i]=i;
}
get(1,n,1,ttp);
for(int i=1;i<=ttp;i++){
write(ans[i]);
}
return fw,0;
}
浙公网安备 33010602011771号