样例输入:
5 3
1 4 2 8 7
样例输出:
17
分析:这道题我想的比较复杂,不过复杂度还是够用的,我是用线段树+二分来做的。
我们用线段树维护所有位置的最小值,那么我们每次删除一个数之前先求一遍最小值,不妨设最小值为mn,然后从左边开始找第一个值为mn的位置,不妨设位置为pos,我们每次删除一个数,就把这个位置设置为0x3f3f3f3f3f3f3f3f,因为可能爆int,所以设置为longlong里面的较大值。这样我们当前要删除pos位置的数,那么就把pos位置的数设置为0x3f3f3f3f3f3f3f3f,然后从pos-1向前二分寻找第一个位置i使得区间[i,pos-1]的最小值不为0x3f3f3f3f3f3f3f3f,这就是现存的左边相邻的数,同理从pos+1向后二分寻找第一个位置i使得区间[pos+1,i]的最小值不为0x3f3f3f3f3f3f3f3f,这就是现存的右边相邻的数,然后把这两个数都加上mn即可。
最后我们直接把那些位置不为0x3f3f3f3f3f3f3f3f的数输出即可。
细节见代码:
#include
#include
#include
#include
#include
using namespace std;
const int N=2e6+10;
long long mn[N];
int l[N],r[N];
void pushup(int id)
{
mn[id]=min(mn[id<<1],mn[id<<1|1]);
return ;
}
void build(int id,int L,int R)
{
l[id]=L;r[id]=R;
if(L==R)
{
scanf("%lld",&mn[id]);
return ;
}
int mid=L+R>>1;
build(id<<1,L,mid);
build(id<<1|1,mid+1,R);
pushup(id);
}
void update_point(int id,int pos,long long x)
{
if(l[id]==r[id])
{
mn[id]+=x;
return ;
}
int mid=l[id]+r[id]>>1;
if(pos<=mid) update_point(id<<1,pos,x);
else update_point(id<<1|1,pos,x);
pushup(id);
}
long long query_interval(int id,int L,int R)
{
if(l[id]>=L&&r[id]<=R) return mn[id];
int mid=l[id]+r[id]>>1;
long long ans=0x3f3f3f3f3f3f3f3f;
if(L<=mid) ans=min(ans,query_interval(id<<1,L,R));
if(mid+1<=R) ans=min(ans,query_interval(id<<1|1,L,R));
return ans;
}
int main()
{
int n,k;
scanf("%d%d",&n,&k);
build(1,1,n);
// for(int i=1;i<=n;i++)
// for(int j=i;j<=n;j++)
// printf("%d %d %lld\n",i,j,query_interval(1,i,j));
while(k--)
{
long long mi=query_interval(1,1,n);
int l=1,r=n;
while(l>1;
if(query_interval(1,1,mid)<=mi) r=mid;
else l=mid+1;
}
long long val=query_interval(1,l,l);
// printf("%lld\n",val);
update_point(1,l,0x3f3f3f3f3f3f3f3f-val);
// if(query_interval(1,l,l)==0x3f3f3f3f3f3f3f3f) puts("11111111111");
int t=l;
if(t!=1)//更新左边
{
l=1,r=t-1;
while(l>1;
if(query_interval(1,mid,t-1)!=0x3f3f3f3f3f3f3f3f) l=mid;
else r=mid-1;
}
if(query_interval(1,l,t-1)!=0x3f3f3f3f3f3f3f3f)
{
// printf("%d\n",l);
update_point(1,l,val);
}
}
if(t!=n)//更新右边
{
l=t+1,r=n;
while(l>1;
if(query_interval(1,t+1,mid)!=0x3f3f3f3f3f3f3f3f) r=mid;
else l=mid+1;
}
if(query_interval(1,t+1,l)!=0x3f3f3f3f3f3f3f3f)
{
// printf("%d\n",l);
update_point(1,l,val);
}
}
}
for(int i=1;i<=n;i++)
{
long long val=query_interval(1,i,i);
if(val!=0x3f3f3f3f3f3f3f3f) printf("%lld ",val);
}
return 0;
}