csp 模擬賽。
A.
暴力列舉就行。
B.
中序遍歷,然後就變為了給定一個序列 \(p\),求最少修改幾次能讓 \(p\) 變的單調遞增,並且滿足 \(p_i - p_j \ge i - j (i > j)\),變換一下就是 \(p_i - i \ge p_j - j\),所以中序遍歷完了之後 \(p_i\) 減去 \(i\),後答案即為 \(ans - lis\)。
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N = 1e6 + 7;
int a[N];
int p[N];
int cnt;
int ch[N][2];
void dfs(int u) {
if(ch[u][0]) dfs(ch[u][0]);
p[++ cnt] = a[u] - cnt;
if(ch[u][1]) dfs(ch[u][1]);
}
struct node {
int val, id;
}e[N];
int b[N];
signed main() {
int n;
cin >> n;
for(int i = 1; i <= n; i ++) {
cin >> a[i];
}
for(int i = 2; i <= n; i ++) {
int x, y;
cin >> x >> y;
ch[x][y] = i;
}
dfs(1);
int len = 0;
for(int i = 1; i <= n; i ++) {
if(p[i] >= b[len]) {
b[++ len] = p[i];
}
else {
int j = lower_bound(b + 1, b + len + 1, p[i]) - b;
b[j] = p[i];
}
}
cout << n - len << endl;
}
C.
二分長度 \(l\),st 表維護區間 gcd 和區間最小值,時間複雜度 \(O(nlogn)\)
#include<bits/stdc++.h>
using namespace std;
const int N = 5e5 + 500;
int a[N];
int fgcd[N][32], rmin[N][32];
int gcd(int x, int y)
{
while(y)
{
x%=y;
swap(x,y);
}
return x;
}
int getgcd(int l, int r) {
int k = log2(r - l + 1);
return gcd(fgcd[l][k], fgcd[r - (1 << k) + 1][k]);
}
int n;
int getmin(int l, int r) {
int k = log2(r - l + 1);
return min(rmin[l][k], rmin[r - (1 << k) + 1][k]);
}
int check(int l) {
for(int i = 1; i <= n - l; i ++) {
if(getgcd(i, i + l) % getmin(i, i + l) == 0 ) {
return 1;
}
}
return 0;
}
int main() {
memset(rmin, 0x3f, sizeof rmin);
cin >> n;
for(int i = 1; i <= n; i ++) {
cin >> a[i];
fgcd[i][0] = rmin[i][0] = a[i];
}
for(int j = 1; j < 23; j ++) {
for(int i = 1; i <= n - (1 << (j - 1)); i ++) {
fgcd[i][j] = gcd(fgcd[i][j - 1], fgcd[i + (1 << (j - 1))][j - 1]);
}
}
//
for(int j = 1; j < 23; j ++) {
for(int i = 1; i <= n - (1 << (j - 1)); i ++) {
rmin[i][j] = min(rmin[i][j - 1], rmin[i + (1 << (j - 1))][j - 1]);
}
}
int l = 0, r = n;
int ans;
while(l <= r) {
int mid = l + r >> 1;
if(check(mid)) {
l = mid + 1;
ans = mid;
}
else {
r = mid - 1;
}
}
vector<int> v;
int cnt = 0;
for(int i = 1; i <= n - ans; i ++) {
if(getgcd(i, i + ans) % getmin(i, i + ans) == 0 ) {
cnt ++;
v.push_back(i);
}
}
cout << cnt << " " << ans << endl;
for(int i = 0; i < cnt; i ++) cout << v[i] << " ";
}