题解 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;
}