​题目链接​

在群里和群友扯淡,遇到这道题,本以为是水题,写了写,有情况没有考虑,发现并不水,有大佬用贪心过了,咱也不太想去想贪心,虽然有呢么个思路,但发现不太稳,没有什么严谨的科学证明,然后发现用线段树缩一下区间就可以,就试着写了一下,然后题目比较水,数据范围给错了,然后就用3倍的线段树给过了

题意:

求长度为k的序列的最大字典序

AC代码:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const ll maxn=1e5+5;
struct node
{
ll id,a;
} p[maxn];
bool cmp(node x,node y)
{
if(x.a==y.a)
return x.id>y.id;
return x.a<y.a;
}
ll c[maxn],ans[maxn],ikx;
struct vain
{
ll l,r,maxx,idx;
}tr[maxn<<2];
void pushup(ll k)
{
if(tr[k<<1].maxx>=tr[k<<1|1].maxx)
{
tr[k].maxx=tr[k<<1].maxx;
tr[k].idx=tr[k<<1].idx;
}
else
{
tr[k].maxx=tr[k<<1|1].maxx;
tr[k].idx=tr[k<<1|1].idx;
}
}
void build(ll k,ll l,ll r)
{
tr[k].l=l,tr[k].r=r;
if(l==r)
{
tr[k].maxx=c[l];
tr[k].idx=l;
return ;
}
ll mid=l+r>>1;
build(k<<1,l,mid);
build(k<<1|1,mid+1,r);
pushup(k);
}
ll ask(ll k,ll l,ll r)
{
if(tr[k].l>=l&&tr[k].r<=r)
{
return k;
}
ll mid=tr[k].l+tr[k].r>>1;
if(r<=mid)
{
return ask(k<<1,l,r);
}
else if(l>mid)
{
return ask(k<<1|1,l,r);
}
else
{
if(tr[ask(k<<1,l,mid)].maxx>=tr[ask(k<<1|1,mid+1,r)].maxx)
return ask(k<<1,l,mid);
else
return ask(k<<1|1,mid+1,r);
}
}
int main()
{
ios::sync_with_stdio(false);
ll n,k;
while(cin>>n>>k)
{
memset(ans,0,sizeof(ans));
for(ll i=1; i<=n; i++)
cin>>p[i].a,p[i].id=i,c[i]=p[i].a;
sort(p+1,p+n+1,cmp);
ll t,o=0,j=0;
for(ll i=n; i>=1; i--)
{
if(n-p[i].id+1>=k)
{
t=p[i].id;
ans[++o]=p[i].a;
k--;
break;
}
}
for(ll i=t+1; i<=n; i++)
c[++j]=c[i];
build(1,1,j);
ll lx=1,rx=j,q=j,u;
while(1)
{
if(k==0)
break;
u=ask(1,lx,rx);
if(q-tr[u].idx+1>=k)
{
rx=q;
lx=tr[u].idx+1;
ans[++o]=tr[u].maxx;
k--;
}
else
{
rx=tr[u].idx-1;
}
}
for(ll i=1;i<=o;i++)
if(i==o)
cout<<ans[i]<<endl;
else
cout<<ans[i]<<' ';
}
}