NOIP2015普及组 推销员
啊这道题自己写的怪怪的……127行啊……而且最后速度也不是很快……
解法:线段树(最近学这个所以就用这个做了)
别看代码……很怪的……
#include<cstdio>
#define MAXN 100005
using namespace std;
const int INF = (int)((long long)(2<<30) - 1);
struct Segment_tree{
long long max,dis;
int num,tag;
}Seg[MAXN<<2];
long long dis[MAXN];
int N;
inline int read(){
char ch=getchar();
int num=0,f=1;
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9')num=num*10+ch-48,ch=getchar();
return num*f;
}
inline void write(long long x){
if(x>9)write(x/10);
putchar(x%10+'0');
}
inline void PushUp(int rt){
if(Seg[rt<<1].max+Seg[rt<<1].dis>Seg[rt<<1|1].max+Seg[rt<<1|1].dis){
Seg[rt].max = Seg[rt<<1].max;
Seg[rt].dis = Seg[rt<<1].dis;
Seg[rt].num = Seg[rt<<1].num;
}
else{
Seg[rt].max = Seg[rt<<1|1].max;
Seg[rt].dis = Seg[rt<<1|1].dis;
Seg[rt].num = Seg[rt<<1|1].num;
}
}
inline void Build(int l,int r,int rt){
if(l==r){
Seg[rt].max=(long long)read();
Seg[rt].dis=dis[l];
Seg[rt].num=l;
Seg[rt].tag=0;
return;
}
int m = (l+r)>>1;
Build(l,m,rt<<1);
Build(m+1,r,rt<<1|1);
PushUp(rt);
}
inline void Pushdown(int sizel,int sizer,int rt){
int add = Seg[rt].tag;Seg[rt].tag = 0;
int l = rt<<1;int r = rt<<1|1;
Seg[l].tag+=add;Seg[r].tag+=add;
Seg[l].dis+=(long long)sizel*add;
Seg[r].dis+=(long long)sizer*add;
if(Seg[l].dis<0)Seg[l].dis=0;if(Seg[r].dis<0)Seg[r].dis=0;
}
inline void ReBuild(int L,int R,int l,int r,int rt){
if(L>r||l>R)return;
if(l==r){
Seg[rt].dis=0;
return;
}
int m = (l+r)>>1;
Pushdown((m-l+1),(r-m),rt);
if(L<=m)ReBuild(L,R,l,m,rt<<1);
if(R>m)ReBuild(L,R,m+1,r,rt<<1|1);
PushUp(rt);
}
inline void Update(int L,int R,int C,int l,int r,int rt){
if(L>r||l>R)return;
if(L<=l&&R>=r){
Seg[rt].dis+=C;
if(Seg[rt].dis<0)Seg[rt].dis=0;
Seg[rt].tag+=C;
return;
}
int m = (l+r)>>1;
Pushdown((m-l+1),(r-m),rt);
if(L<=m)Update(L,R,C,l,m,rt<<1);
if(R>m)Update(L,R,C,m+1,r,rt<<1|1);
PushUp(rt);
}
inline void Single(int P,int l,int r,int rt){
if(l==r){
Seg[rt].max=0;
Seg[rt].dis=0;
return;
}
int m = (l+r)>>1;
Pushdown((m-l+1),(r-m),rt);
if(P<=m)Single(P,l,m,rt<<1);
else Single(P,m+1,r,rt<<1|1);
PushUp(rt);
}
int main(){
N=read();
for(register int i=1;i<=N;i++){
dis[i]=(long long)(read())<<1;
}
Build(1,N,1);
long long ans = 0;
int last = -INF;
int Nul = 1;
for(register int i=1;i<=N;i++){
ans += Seg[1].max+Seg[1].dis;
write(ans);putchar('\n');
if(i==N)return 0;
int ago = Seg[1].num;
if(dis[ago]>last){
last = dis[ago];
if(ago-1>=Nul)ReBuild(Nul,ago-1,1,N,1),Nul=ago;
if(ago+1<=N)Update(ago+1,N,-last,1,N,1);
}
Single(ago,1,N,1);
}
return 0;
}