https://www.luogu.org/problemnew/show/P2672
题 意 很 简 单 , p a s s 题意很简单,pass 题意很简单,pass
题解:题目说了:在不走多余路的前提下,求最大的疲劳值。不走多余路意思就是不能绕来绕去地走,也就是往前走到最远处后只能往回走,不能有两次以上的折返。因此可以直接贪心。
对于 x = 1 x=1 x=1的情况,答案肯定就是 2 ∗ s [ i ] + a [ i ] 2*s[i] +a[i] 2∗s[i]+a[i]中的最大值,更新一下这个最大值的下标id,表示能到达的最远点
对于 x > 1 x>1 x>1的情况,那么就分为两种:一种在最远点id的左侧,那么对答案的贡献是 a [ i ] a[i] a[i],另一种在id的右侧,对答案的贡献是$
2 ∗ s [ i ] − 2 ∗ s [ i d ] + a [ i ] 2*s[i]-2*s[id]+a[i] 2∗s[i]−2∗s[id]+a[i]
我们只需要判断这两种贡献的大小,然后不断更新最远点的下标 i d id id 就ok了。
贪心思路想好后,对 a [ i ] a[i] a[i]和 2 ∗ s [ i ] + a [ i ] 2*s[i]+a[i] 2∗s[i]+a[i]分别建树(t1,t2),用线段树维护区间最大值。
每选中一个点,如果这个点在最远点 i d id id的左侧,那么将t1线段树对应的点更新为0,对t2相同
#include
using namespace std;
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
typedef long long ll;
const int mx = 1e5+5;
struct node{
ll val;
int id;
node(ll x = 0,int y = 0){val = x,id = y;}
friend bool operator <(const node& a, const node& b){
if(a.val != b.val) return a.val < b.val;
return a.id > b.id;
}
}t1[mx<<2],t2[mx<<2];
ll s[mx];
ll a[mx];
void pushup(int rt){
t1[rt] = max(t1[rt<<1],t1[rt<<1|1]);
t2[rt] = max(t2[rt<<1],t2[rt<<1|1]);
}
void build(int l,int r,int rt){
if(l == r){
t1[rt].val = a[l];
t1[rt].id = l;
t2[rt].val = 2ll*s[l]+a[l];
t2[rt].id = l;
return;
}
int mid = (l+r)>>1;
build(lson);
build(rson);
pushup(rt);
}
void update1(int l,int r,int rt,int pos){
if(l == r){
t1[rt] = node(0,0);
return;
}
int mid = (l+r)>>1;
if(pos <= mid) update1(lson,pos);
else update1(rson,pos);
pushup(rt);
}
void update2(int l,int r,int rt,int pos){
if(l == r){
t2[rt] = node(0,0);
return;
}
int mid = (l+r)>>1;
if(pos <= mid) update2(lson,pos);
else update2(rson,pos);
pushup(rt);
}
node query1(int l,int r,int rt,int L,int R){
if(L > R) return node(0,0);
if(L <= l && R >= r){
return t1[rt];
}
int mid = (l+r)>>1;
node xx(0,0);
if(L <= mid) xx = max(xx,query1(lson,L,R));
if(R > mid) xx = max(xx,query1(rson,L,R));
return xx;
}
node query2(int l,int r,int rt,int L,int R){
if(L > R) return node(0,0);
if(L <= l && R >= r){
return t2[rt];
}
int mid = (l+r)>>1;
node xx(0,0);
if(L <= mid) xx = max(xx,query2(lson,L,R));
if(R > mid) xx = max(xx,query2(rson,L,R));
return xx;
}
int n;
int main(){
cin>>n;
for(int i = 1; i <= n; i++){
scanf("%lld",&s[i]);
}
for(int i = 1; i <= n; i++){
scanf("%lld",&a[i]);
}
build(1,n,1);
node ans1 = query1(1,n,1,1,n);
node ans2 = query2(1,n,1,1,n);
int id; ll ans = 0;
if(ans1.val > ans2.val){
ans = ans1.val;
id = ans1.id;
}else{
ans = ans2.val;
id = ans2.id;
}
update1(1,n,1,id);
update2(1,n,1,id);
printf("%lld\n",ans);
for(int x = 2; x <= n; x++){
ans1 = query1(1,n,1,1,id-1);
ans2 = query2(1,n,1,id+1,n);
ll tmp = ans2.val-2*s[id];
/*printf("s1:%d %d\n",ans1.val,ans1.id);
printf("s2:%d %d\n",ans2.val,ans2.id);*/
if(ans1.val > tmp){
ans += ans1.val;
update1(1,n,1,ans1.id);
//update2(1,n,1,id);
}else{
ans += tmp;
id = ans2.id;
update2(1,n,1,id);
}
printf("%lld\n",ans);
}
}