Gym 100956 A Random Points on the Circle

二分答案。

对于每次二分后的答案来说, 

  先倍增序列,通过 two point 来找到 以每个点为起点的最优的符合答案的在哪里。

  然后可以DFS树去判断他的前k祖先之间的距离是不是大于k。 常数有点大。

  在 ID为 WuHongxun 的代码下学会了, 先判断一下最小一段的跨度, 如果跨度 >= n / k + 1 那么直接就是合法的了。

  否则枚举最小跨度内的点作为起点, 直接走k步, 判断一下是否合法。

代码:

#include<bits/stdc++.h>
using namespace std;
#define Fopen freopen("_in.txt","r",stdin); freopen("_out.txt","w",stdout);
#define LL long long
#define ULL unsigned LL
#define fi first
#define se second
#define pb push_back
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define lch(x) tr[x].son[0]
#define rch(x) tr[x].son[1]
#define max3(a,b,c) max(a,max(b,c))
#define min3(a,b,c) min(a,min(b,c))
typedef pair<int,int> pll;
const int inf = 0x3f3f3f3f;
const int _inf = 0xc0c0c0c0;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const LL _INF = 0xc0c0c0c0c0c0c0c0;
const LL mod =  (int)1e9+7;
const int N = 2e6 + 100;
LL L = 1 << 30;
int n, k, seed, add;
LL d[N], s[N];
int nt[N];
inline LL cal(int l, int r){
    return (s[r] - s[l+r>>1]) - (s[(l+r-1)>>1] - s[l-1]);
}
bool check(LL x){
    int mn = 2 * n + 1, id;
    for(int i = 1, j = 1; i <= n * 2; ++i){
        while(j <= 2 * n && cal(i,j) <= x) ++j;
        nt[i] = j;
        if(i <= n && j-i < mn){
            mn = j - i;
            id = i;
        }
    }
    if(mn >= n/k + 1) return true;
    for(int i = id, ed = nt[i]%n+1; i != ed; i = i%n +1){
        int z = i;
        for(int j = 1; j <= k; ++j){
            z = nt[z];
            if(i + n <= z) return true;
        }
    }
    return false;

}
void Ac(){
    scanf("%d%d", &n, &k);
    scanf("%d%d", &seed, &add);
    for(int i = 1; i <= n; ++i){
        seed = (seed * 239017 + add) & (L-1);
        d[i] = seed;
    }
    sort(d+1, d+1+n);
    for(int i = 1; i <= n; ++i)
        d[i+n] = d[i] + L;
    for(int i = 1; i <= 2*n; ++i)
        s[i] = s[i-1] + d[i];
    LL l = 0, r = L * n / k;
    while(l <= r){
        LL mid = l+r >> 1;
        if(!check(mid)) l = mid + 1;
        else r = mid - 1;
    }
    cout << l << endl;
    return ;
}
int main(){
    Ac();
    return 0;
}
View Code

猜你喜欢

转载自www.cnblogs.com/MingSD/p/10622170.html