A.
\(kx + (\sum_{i=1}^{k} a_i - 1) \times y = k(x - y) + y \times \sum_{i=1}^{k} a_i\)
\((a_1 - 1) * 1 + (a_2 - 1) * (a_1 - 1) * 1 + (a_3 - 1) * (a_2 - 1) * (a_1 - 1) * 1\)
$ \prod_{i=1}^{k} a_i > N$
两数和相等时乘积最大,因此 \(a\) 数组中任意两个数的差的绝对值小于等于1(一定是形如 \(p, p + 1\))。
设有 \(t\) 个 \(p\)。
\(p^t \times (p + 1) ^ {k-t} > N\)
\(k(x - y) + y \times (t \times p + (k - t) \times (p + 1)) = k(x-y) + y \times (k \times p + k - t)\)
变成了满足一式的情况下要求二式最小。
枚举 \(k\) 是 \(\log N\),可以再枚举一个 \(t\),再对 \(p\) 二分。
时间复杂度 \(\log ^4 N\)。
代码
#include<bits/stdc++.h>
#define int __int128
using namespace std;const int N = 1e6 + 7;
const int M = 61;
const int inf = 1e20;
void write(int x)
{if(x<0)putchar('-'),x=-x;if(x>9)write(x/10);putchar(x%10+'0');return;
}
inline int read()
{int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0' && ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;
}
signed main() {freopen("dice.in", "r", stdin);freopen("dice.out", "w", stdout);int N, x, y;N = read(), x = read(), y = read();int ans = inf;for(int k = 1; k <= M; k ++) {int l = 0, r = inf;for(int t = 1; t <= k; t ++) {int l = 0, r = inf;int res;while(l <= r) {int mid = l + r >> 1;int flag;int now = 1;int ck = 1;for(int i = 1; i <= t; i ++) {now = now * mid;if(now > N) {ck = 0;break;}}if(!ck) flag = 1;if(ck) {for(int i = 1; i <= k - t; i ++) {now = now * (mid + 1);if(now > N) {ck = 0;break;}}}if(!ck) flag = 1;if(ck && now > N) flag = 1;else if(ck) flag = 0;if(flag) {res = mid;r = mid - 1;}else l = mid + 1;}// cout << k * (x - y) + y * (k * res + k - t) << endl;ans = min(ans, (k * (x - y) + y * (k * res + k - t)));}}write(ans);
}
B.
好题。
设 \(L_i (j)\) 表示序列中等于 \(i\) 的第 \(j\) 个出现的位置。我们要找最小的 \(k\),使得 \(L_k(j) - L_k(j-1) > x\),记 \(f_i\) 表示 \(L_i(j) - L_i(j-1)\) 的最大值, \(G(i)\) 表示 \(\max_{j=1}^{i}f(j)\),要求的就是最小的 \(k\) 使得 \(G(k) > x\)。
对于交换 \(a_p, a_{p+1}\),找到 \(x, y\) 满足 \(L_{a[p]}(x) = p, L_{a_[p+1]}(y) = p + 1\), \(L_{a[p]}[x] ++,L_{a[p + 1]}[y] --\)。然后用线段树维护 \(G\),每次查询二分即可,时间复杂度 \(O(q\log^2n)\)
代码
#include<bits/stdc++.h>
using namespace std;const int N = 5e5 + 10;int a[N];struct tree {int l, r;int mxx;
}T[N << 2];void build(int l, int r, int rt = 1) {T[rt].l = l, T[rt].r = r;if(l == r) {return;}int mid = l + r >> 1;build(l, mid, rt << 1);build(mid + 1, r, rt << 1 | 1);T[rt].mxx = max(T[rt << 1].mxx, T[rt << 1 | 1].mxx);
}
void modify(int pos, int x, int rt = 1) {if(T[rt].l == T[rt].r) {T[rt].mxx = x;return;}int mid = T[rt].l + T[rt].r >> 1;if(pos <= mid) modify(pos, x, rt << 1);else modify(pos, x, rt << 1 | 1);T[rt].mxx = max(T[rt << 1].mxx, T[rt << 1 | 1].mxx);
}
int query(int l, int r, int rt = 1) {if(l <= T[rt].l && r >= T[rt].r) {return T[rt].mxx;}int mid = T[rt].l + T[rt].r >> 1;int ans = -1;if(l <= mid) ans = max(ans, query(l, r, rt<< 1));if(r > mid) ans = max(ans, query(l, r, rt << 1 | 1));return ans;
}
set<int> L[N];
multiset<int> dis[N];void ins(int x) {auto it = L[a[x]].lower_bound(x);int r = *it, l = *(--it);L[a[x]].insert(x);dis[a[x]].erase(dis[a[x]].lower_bound(r - l - 1));dis[a[x]].insert(r - x - 1);dis[a[x]].insert(x - l - 1);modify(a[x] + 1, *dis[a[x]].rbegin());
}
void del(int x) {L[a[x]].erase(x);auto it = L[a[x]].lower_bound(x);int r = *it, l = *(--it);dis[a[x]].insert(r - l - 1);dis[a[x]].erase(dis[a[x]].lower_bound(r - x - 1));dis[a[x]].erase(dis[a[x]].lower_bound(x - l - 1));modify(a[x] + 1, *dis[a[x]].rbegin());
}
int main() {ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);freopen("star.in", "r", stdin);freopen("star.out", "w", stdout);int n, q;cin >> n >> q;build(1, n + 1);for(int i = 0; i < n; i ++) {L[i].insert(0), L[i].insert(n + 1);dis[i].insert(n + 1);modify(i + 1, n + 1);}for(int i = 1; i <= n; i ++) {cin >> a[i];ins(i);}while(q --) {int x, y;cin >> x >> y;if(x == 1) {del(y);del(y + 1);swap(a[y], a[y + 1]);ins(y);ins(y + 1);}else {int l = 1, r = n;int ans = n + 1;while(l <= r) {int mid = l + r >> 1;if(query(1, mid) >= y) {ans = mid;r = mid - 1;}else l = mid + 1;}cout << ans - 1 << endl;}}
}