[NOIP 2015] 推销员 - 洛谷
核心:利用线段树处理贪心内容。建两个线段树维护两端。
#include<bits/stdc++.h>
using namespace std;
int n;
int d[100100];
int t[1000100];
int deep;//当前最深
int ans;
struct node{
int id,mx;
};
struct sgt{
int a[1000100];
int mx[4000100];
int id[4000100];
void build(int p,int l,int r){
if(l == r){
mx[p] = a[l];
id[p] = l;
return;
}
int mid = (l+r)/2;
build(p*2,l,mid);
build(p*2+1,mid+1,r);
if(mx[p*2]>mx[p*2+1]){
mx[p] = mx[p*2];
id[p] = id[p*2];
}
else{
mx[p] = mx[p*2+1];
id[p] = id[p*2+1];
}
}
void update(int p,int L,int R,int ID,int x){
if(L == R){
mx[p] = x;
return;
}
int mid = (L+R)/2;
if(ID <= mid)update(p*2,L,mid,ID,x);
else update(p*2+1,mid+1,R,ID,x);
if(mx[p*2]>mx[p*2+1]){
mx[p] = mx[p*2];
id[p] = id[p*2];
}
else{
mx[p] = mx[p*2+1];
id[p] = id[p*2+1];
}
}
node query(int p,int L,int R,int l,int r){
if(l == L&&R == r){
return node{id[p],mx[p]};
}
int mid = (L+R)/2;
if(r <= mid){
return query(p*2,L,mid,l,r);
}
else if(l > mid){
return query(p*2+1,mid+1,R,l,r);
}
else{
node LL = query(p*2,L,mid,l,mid);
node RR = query(p*2+1,mid+1,R,mid+1,r);
if(LL.mx > RR.mx){
return LL;
}
else{
return RR;
}
}
}
}t1,t2;
int main(){
cin>>n;
for(int i = 1;i <= n;i++){
cin>>d[i];
}
for(int i = 1;i <= n;i++){
cin>>t[i];
t2.a[i] = 2*d[i]+t[i];
t1.a[i] = t[i];
}
t1.build(1,1,n);
t2.build(1,1,n);
for(int i = 1;i <= n;i++){
node L = {-1,-1},R = {-1,-1};
// cout<<i<<endl;
if(deep > 0){
L = t1.query(1,1,n,1,deep);
}
if(deep < n){
//cout<<"UES"<<endl;
R = t2.query(1,1,n,deep+1,n);
}
//cout<<R.mx-2*d[deep]<<" "<<R.id<<" "<<L.mx<<" "<<L.id<<endl;
if(R.mx-2*d[deep] >= L.mx){
ans+=R.mx-2*d[deep];
t2.update(1,1,n,R.id,-2);
t1.update(1,1,n,R.id,-2);
deep = R.id;
}
else{
ans+=L.mx;
t1.update(1,1,n,L.id,-1);
t2.update(1,1,n,L.id,-2);
}
cout<<ans<<endl;
}
return 0;
}