AT_abc480_g 题解
这个 G 很简单啊,居然只过了不到三百人(指指点点。
哦我怎么赛后 5min 才过,我是区区!我爱蠕动!我要飞起来!
做完 F 后给我的时间不多了。
严肃阅读了 G 题并意识到与某道最近的模拟赛 T2 维护
首先你可以发现有基础的
前面的
不难想到单调栈维护当前的
那么就做完了,实现上有一些细节,需要调一阵子(要不是因为我调了好一会我赛时都做出来了 www),具体可以参考一下我的代码喵。
我的代码里也有很多调试记录(为了观感,下面展出的代码将调试删掉了),在 submission 里其实也可以看到我是调的挺烦的。
::::success[code && submission]
#include<bits/stdc++.h>
#define LL long long
#define UInt unsigned int
#define ULL unsigned long long
#define LD long double
#define pii pair<int,int>
#define pLL pair<LL,LL>
#define pDD pair<LD,LD>
#define fr first
#define se second
#define pb push_back
#define isr insert
#define _i128 __int128
using namespace std;
const int N = 2e5+5;
const LL INF = 2e18+1099;
struct node{LL l,r,val;};
struct SegT{LL val,tag;}t[N<<2];
LL n,a[N],dp[N];
int mx_top,mn_top;
node mx_st[N],mn_st[N];
LL read(){
LL su=0,pp=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')pp=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){su=su*10+ch-'0';ch=getchar();}
return su*pp;
}
int ls(int u){return (u<<1);}
int rs(int u){return (u<<1|1);}
void push_up(int u){
t[u].val=min(t[ls(u)].val,t[rs(u)].val);
return;
}
void add_tag(int u,LL k){
t[u].val+=k,t[u].tag+=k;
return;
}
void push_down(int u){
if(!t[u].tag)return;
add_tag(ls(u),t[u].tag);
add_tag(rs(u),t[u].tag);
t[u].tag=0;return;
}
void change(int u,int l,int r,int L,int R,LL k){
if(r<L||R<l)return;
if(L<=l&&r<=R){add_tag(u,k);return;}
int mid=(l+r)>>1;push_down(u);
change(ls(u),l,mid,L,R,k);
change(rs(u),mid+1,r,L,R,k);
push_up(u);return;
}
LL ask(int u,int l,int r,int L,int R){
if(R<L||r<L||R<l)return INF;
if(L<=l&&r<=R)return t[u].val;
int mid=(l+r)>>1;push_down(u);
return min(ask(ls(u),l,mid,L,R),ask(rs(u),mid+1,r,L,R));
}
int main(){
n=read();
for(int i=1;i<=n;i++)a[i]=read();
change(1,1,n+1,1,1,0);
for(int i=1;i<=n;i++){
int now=i;
while(mx_top&&mx_st[mx_top].val<=a[i]){
node tmp=mx_st[mx_top--];
change(1,1,n+1,tmp.l,tmp.r,a[i]-tmp.val);
now=tmp.l;
}
mx_st[++mx_top]={now,i,a[i]};
now=i;
while(mn_top&&mn_st[mn_top].val>=a[i]){
node tmp=mn_st[mn_top--];
change(1,1,n+1,tmp.l,tmp.r,tmp.val-a[i]);
now=tmp.l;
}
mn_st[++mn_top]={now,i,a[i]};
dp[i]=ask(1,1,n+1,1,i-1);
change(1,1,n+1,i+1,i+1,dp[i]);
}
cout<<dp[n]<<"\n";
return 0;
}
::::
或许,这也算是某种意义上的第一次切 G 了呢?至少曾经的任何一道 G 都没有在不看题解的情况下补出来过。
不过我还是相信我能够飞起来的。
如果本篇题解对你有帮助的话,麻烦你点一个小小的赞,真是太感谢啦!