用线段树维护每个点的相对位置(即该结点及该结点之前共有多少个结点),因此算出相对位置后即可用线段树
O(logn)
找出绝对位置。
用区间修改单点查询的线段树。
#include<bits/stdc++.h>
using namespace std;
const int maxn=2e5+7;
int pre[maxn<<2],lz[maxn<<2];
int ql,qr,pos;
void push_up(int rt)
{
pre[rt]=max(pre[rt<<1],pre[rt<<1|1]);
}
void build(int rt,int l,int r)
{
if(l==r)
{
pre[rt]=l;
return ;
}
int mid=(l+r)>>1;
build(rt<<1,l,mid);
build(rt<<1|1,mid+1,r);
push_up(rt);
}
void push_down(int rt)
{
if(lz[rt]==0) return;
lz[rt<<1]+=lz[rt];
lz[rt<<1|1]+=lz[rt];
pre[rt<<1]+=lz[rt];
pre[rt<<1|1]+=lz[rt];
lz[rt]=0;
}
void update(int rt,int l,int r)
{
if(l>=ql&&r<=qr)
{
--pre[rt];
--lz[rt];
return;
}
int mid=(l+r)>>1;
push_down(rt);
if(ql<=mid) update(rt<<1,l,mid);
if(qr>mid) update(rt<<1|1,mid+1,r);
push_up(rt);
}
int query(int rt,int l,int r)
{
if(l==r) return l;
push_down(rt);
int mid=(l+r)>>1;
if(pre[rt<<1]>=pos) return query(rt<<1,l,mid);
else return query(rt<<1|1,mid+1,r);
}
int main()
{
int n,k;
scanf("%d%d",&n,&k);
build(1,1,n);
int cnt=n;
pos=1;
for(int i=0;i<n;i++)
{
pos=(pos-2+k+cnt*2)%cnt+1;
--cnt;
int res=query(1,1,n);
printf("%d%c",res,i+1==n?'\n':' ');
ql=res;qr=n;
update(1,1,n);
}
return 0;
}