列表

详情


NC201978. King

描述

序列是胖的当且仅当存在实数满足
  1. 对于所有的,存在 满足 .
给定序列, 请问B的最长胖子串有多长?

输入描述

第一行一个正整数  ()。
第二行 个整数 (对于所有的 ,)。

输出描述

一行一个整数表示答案。

示例1

输入:

6
1 1 2 4 8 16

输出:

6

示例2

输入:

7
1 1 2 4 8 16 100

输出:

6

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++14(g++5.4) 解法, 执行用时: 123ms, 内存消耗: 40732K, 提交时间: 2020-02-15 23:56:50

#include <bits/stdc++.h>
using namespace std;
typedef double db;
#define mid ((l + r) >> 1)

const int N = 1e5 + 5;
const int M = 25;
const int bit = 18;
int n, b[N];
int ans, lg[N];
db lf[N][M], rg[N][M];

void solve(void);
bool check(int s, int x);

int main(void) { return solve(), 0; }

void solve(void) {
    scanf("%d", &n), ans = 1, scanf("%d", b + 1);
    for(int i = 2; i <= n; i++) {
        scanf("%d", b + i), lg[i] = lg[i - 1] + (i == (1 << (lg[i - 1] + 1)));
        lf[i][0] = b[i] * 1.0 / (b[i - 1] + 1);
        rg[i][0] = (b[i] + 1) * 1.0 / b[i - 1];
    }
    for(int i = 1; i <= bit; i++)
        for(int j = 1; j <= n - (1 << i) + 1; j++) {
            lf[j][i] = max(lf[j][i - 1], lf[j + (1 << (i - 1))][i - 1]);
            rg[j][i] = min(rg[j][i - 1], rg[j + (1 << (i - 1))][i - 1]);
        }
    for(int i = 1, l, r, e; i < n; i++) {
        l = i + 1, r = n;
        while(l <= r) check(i, mid) ? e = mid, l = mid + 1 : r = mid - 1;
        ans = max(ans, e - i + 1);
    }
    printf("%d\n", ans);
}

inline bool check(int s, int x) {
    db l = max(lf[s + 1][lg[x - s]], lf[x - (1 << lg[x - s]) + 1][lg[x - s]]);
    db r = min(rg[s + 1][lg[x - s]], rg[x - (1 << lg[x - s]) + 1][lg[x - s]]);
    return l < r && r > b[s] && l < b[s] + 1;
}

C++(clang++11) 解法, 执行用时: 90ms, 内存消耗: 39944K, 提交时间: 2021-05-10 17:59:19

#include <bits/stdc++.h>
#define maxn 100086

using namespace std;

struct Frac{
	int x, y;
	
	Frac(){}
	
	Frac(int xx, int yy){
		int gcd = __gcd(xx, yy);
		x = xx / gcd, y = yy / gcd; 
	}
	
	bool operator < (const Frac &f) const {
		return 1ll * x * f.y < 1ll * y * f.x;
	}
	
};

int n;
int a[maxn];
Frac mn[maxn][25], mx[maxn][25];

int main(){
	scanf("%d", &n);
	for(int i = 1;i <= n;i++) scanf("%d", &a[i]);
	for(int i = 2;i <= n;i++) mn[i][0] = Frac(a[i], a[i - 1] + 1), mx[i][0] = Frac(a[i] + 1, a[i - 1]);
	for(int j = 1;j <= 20;j++){
		for(int i = 2;i + (1 << j) - 1 <= n;i++){
			mn[i][j] = max(mn[i][j - 1], mn[i + (1 << (j - 1))][j - 1]);
			mx[i][j] = min(mx[i][j - 1], mx[i + (1 << (j - 1))][j - 1]);
		}
	} 
	int ans = 1;
	for(int i = 1;i < n;i++){
		int x = i + 1;
		Frac l(a[i], 1), r(a[i] + 1, 1);
		for(int j = 20;~j;j--){
			if(x + (1 << j) - 1 > n) continue;
			Frac L = max(l, mn[x][j]), R = min(r, mx[x][j]);
			if(!(L < R)) continue;
			l = L, r = R, x += 1 << j;
		}
		ans = max(ans, x - i);
	}
	printf("%d", ans);
}

上一题