题解 Fable
这场是来搞笑的吧
令 \(inv_i\) 为在位置 \(i\) 前面且比 \(a_i\) 大的数的数量
可以发现每轮这个数恰好 -1
那么 \(k\) 轮后这个数会向前翻 \(\min(k, inv_i)\) 个位置
但是它后面可能会有数翻到它前面
所以从后往前处理,线段树二分找到第 \(\min(k, inv_i)\) 个空位就好了
复杂度 \(O(n\log n)\)
那么事实上是有不用线段树的做法的
考虑最终答案序列的位置 \(i\) 的数一定在原序列的 \([1, i+k]\) 中
那么位置 1 的数一定是 \([1, k]\) 中最小的那个,可以直接确定
然后位置 2 的数就是 \([1, k+1]\) 中第二小的那个,也就可以确定了
于是可以用一个堆直接维护出来
代码量比较惊人:
#include <bits/stdc++.h>
using namespace std;
signed main()
{
freopen("fable.in", "r", stdin), freopen("fable.out", "w", stdout);
priority_queue<int> q;
int n,k,x;
cin>>n>>k;
for(int i=1;i<=k;i++) cin>>x, q.push(-x);
for(int i=k+1;i<=n;i++) cin>>x, q.push(-x), cout<<-q.top()<<endl, q.pop();
for(int i=1;i<=k;i++) cout<<-q.top()<<endl, q.pop();
}
点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define N 200010
#define ll long long
//#define int long long
char buf[1<<21], *p1=buf, *p2=buf;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf, 1, 1<<21, stdin)), p1==p2?EOF:*p1++)
inline int read() {
int ans=0, f=1; char c=getchar();
while (!isdigit(c)) {if (c=='-') f=-f; c=getchar();}
while (isdigit(c)) {ans=(ans<<3)+(ans<<1)+(c^48); c=getchar();}
return ans*f;
}
int n, k;
int a[N];
namespace force{
void solve() {
// cout<<" a: "; for (int i=1; i<=n; ++i) cout<<a[i]<<' '; cout<<endl;
for (int i=1; i<=k; ++i) {
for (int j=1; j<n; ++j)
if (a[j]>a[j+1])
swap(a[j], a[j+1]);
// cout<<setw(2)<<i<<": "; for (int j=1; j<=n; ++j) cout<<a[j]<<' '; cout<<endl;
}
for (int i=1; i<=n; ++i) printf("%d\n", a[i]);
}
}
namespace task1{
int bit[N], uni[N], inv[N], ans[N], usiz;
inline void add(int i, int dat) {for (; i; i-=i&-i) ++bit[i];}
inline int query(int i) {int ans=0; for (; i<=usiz; i+=i&-i) ans+=bit[i]; return ans;}
void ins(int pos, int val) {
for (int i=1; i<=n&&pos; ++i)
if (!ans[i] && --pos==0) ans[i]=val;
}
void solve() {
for (int i=1; i<=n; ++i) uni[++usiz]=a[i];
sort(uni+1, uni+usiz+1);
usiz=unique(uni+1, uni+usiz+1)-uni-1;
for (int i=1; i<=n; ++i) a[i]=lower_bound(uni+1, uni+usiz+1, a[i])-uni;
for (int i=1; i<=n; ++i) inv[i]=query(a[i]+1), add(a[i], 1);
for (int i=n; i; --i) {
int pos=i-min(k, inv[i]);
ins(pos, uni[a[i]]);
}
for (int i=1; i<=n; ++i) printf("%d\n", ans[i]);
}
}
namespace task2{
int bit[N], uni[N], inv[N], ans[N], usiz;
inline void add(int i, int dat) {for (; i; i-=i&-i) ++bit[i];}
inline int query(int i) {int ans=0; for (; i<=usiz; i+=i&-i) ans+=bit[i]; return ans;}
int tl[N<<2], tr[N<<2], val[N<<2];
#define tl(p) tl[p]
#define tr(p) tr[p]
#define pushup(p) val[p]=val[p<<1]+val[p<<1|1]
void build(int p, int l, int r) {
tl(p)=l; tr(p)=r;
if (l==r) {val[p]=1; return ;}
int mid=(l+r)>>1;
build(p<<1, l, mid);
build(p<<1|1, mid+1, r);
pushup(p);
}
void del(int p, int pos) {
if (tl(p)==tr(p)) {val[p]=0; return ;}
int mid=(tl(p)+tr(p))>>1;
if (pos<=mid) del(p<<1, pos);
else del(p<<1|1, pos);
pushup(p);
}
int kth(int p, int k) {
if (tl(p)==tr(p)) return tl(p);
if (k<=val[p<<1]) return kth(p<<1, k);
else return kth(p<<1|1, k-val[p<<1]);
}
void ins(int pos, int val) {
del(1, pos=kth(1, pos));
ans[pos]=val;
}
void solve() {
build(1, 1, n);
for (int i=1; i<=n; ++i) uni[++usiz]=a[i];
sort(uni+1, uni+usiz+1);
usiz=unique(uni+1, uni+usiz+1)-uni-1;
for (int i=1; i<=n; ++i) a[i]=lower_bound(uni+1, uni+usiz+1, a[i])-uni;
for (int i=1; i<=n; ++i) inv[i]=query(a[i]+1), add(a[i], 1);
for (int i=n; i; --i) {
int pos=i-min(k, inv[i]);
ins(pos, uni[a[i]]);
}
for (int i=1; i<=n; ++i) printf("%d\n", ans[i]);
}
}
signed main()
{
freopen("fable.in", "r", stdin);
freopen("fable.out", "w", stdout);
n=read(); k=read();
for (int i=1; i<=n; ++i) a[i]=read();
// force::solve();
// task1::solve();
task2::solve();
return 0;
}