题解 Arcahv

传送门

垃圾出题人是对着做法出的题吧

只会一个 \(O((n+q)\log^2n)\) 的做法:
先考虑一个 \(O(qn\log n)\) 的暴力:
若想让某株草活到第 \(i\) 轮,需要用 \(\leqslant y\) 次交换
使其在 \(2^{k-i}\) 个长为 \(2^i\) 的区间中的至少一个中成为最大值
\(\to\) 小枚举长度,枚举区间,check 区间内 \(>x\) 个数,区间外 \(\leqslant x\) 个数
\(x\) 不在区间内需要至少一步换进来
然后优化这个过程:
对于一个区间以及一个固定的 \(x\),令区间内 \(\leqslant x\) 的数个数为 \(cnt_l\)\(>x\) 个数为 \(cnt_g\)
则这个区间合法的条件是 cntg<=x-cntl && y>=max(cntg, 1)
化简得 x>=len && y>=max(cntg, 1)
那么某个 \(x\) 的答案 \(\geqslant\) 当前枚举的 \(\log_2 {len}\) 的条件就是 \(y\geqslant\) 后面那个东西
显然可以维护
复杂度 \(O((n+q)\log^2n)\)
空间好像得带 \(\log\),离线应该可以不带

然后一个可以过的 \(O(q\log^2n)\) 做法是发现上次答案是 \(\log\) 级别的,所以强制离线
离线做法有点长不想写一遍了,题解里有

然后正解:
更长了,而且比较平凡,就放个链接跑路了
如果链接挂了这里有备份
复杂度 \(O(q\log n)\),空间复杂度 \(O(n)\)

点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define N 525000
#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, q, typ;
char rk[N];
int h[N], pos[N];

namespace force{
	void solve() {
		for (int i=1,x,y,ans=0; i<=q; ++i) {
			x=read()^(ans*typ); y=read()^(ans*typ); ans=rk[pos[x]];
			int all=x;
			for (int step=k-1; step>ans; --step) {
				for (int j=1; j<=n; j+=(1<<step)) {
					int cntl=0, cntg=0;
					for (int t=j; t<j+(1<<step); ++t)
						if (h[t]<=x) ++cntl;
						else ++cntg;
					// if (cntg<=all-cntl && y>=max(cntg, 1)) {ans=step; goto jump;}
					if (all>=(1<<step) && y>=max(cntg, 1)) {ans=step; goto jump;}
				}
			}
			jump: ;
			printf("%d\n", ans);
		}
	}
}

namespace task{
	int *val[20], siz[N<<1], now;
	inline int bel(int i, int j) {return ((1<<k+1)-1)-((1<<k-i+1)-1)+(j-1)/(1<<i)+1;}
	inline void chkmin(int& a, int b) {a=min(a, b);}
	void solve() {
		for (int i=1; i<=k; ++i) {
			val[i]=new int[1<<i|1];
			memset(val[i], 0x3f, sizeof(int)*(1<<i|1));
			val[i][0]=0;
		}
		for (int i=1; i<=k; ++i) {
			for (int j=1; j<=n; ++j) {
				// add j to bel(i, pos[j]):
				chkmin(val[i][++siz[bel(i, pos[j])]], j);
			}
		}
		for (int i=1,x,y,ans=0; i<=q; ++i) {
			x=read()^(ans*typ); y=read()^(ans*typ); ans=rk[pos[x]];
			if (!y) {printf("%d\n", ans); continue;}
			for (int j=k-1; j>ans; --j) if ((1<<j)<=x) {
				if (val[j][max((1<<j)-y, 0)]<=x) {ans=j; break;}
			}
			printf("%d\n", ans);
		}
	}
}

signed main()
{
	freopen("arcahv.in", "r", stdin);
	freopen("arcahv.out", "w", stdout);

	n=read(); k=read(); typ=read();
	for (int i=1; i<=n; ++i) h[i]=read();
	for (int i=1; i<=n; ++i) pos[i]=i;
	for (int i=1; i<n; i<<=1)
		for (int j=1,step=i<<1; j<=n; j+=step)
			if (h[pos[j]]>h[pos[j+i]]) ++rk[pos[j]=pos[j]];
			else ++rk[pos[j]=pos[j+i]];
	for (int i=1; i<=n; ++i) pos[h[i]]=i;
	// cout<<"rk: "; for (int i=1; i<=n; ++i) cout<<rk[i]<<' '; cout<<endl;
	q=read();
	// force::solve();
	task::solve();

	return 0;
}
posted @ 2022-07-26 16:58  Administrator-09  阅读(1)  评论(0编辑  收藏  举报