题解 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;
}
posted @ 2022-04-06 14:13  Administrator-09  阅读(3)  评论(0编辑  收藏  举报