zoukankan      html  css  js  c++  java
  • Gym 100956 A Random Points on the Circle

    二分答案。

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

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

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

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

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

      因为假定最小跨度的区间为 [l, r]。

      必定不存在一个合法区间[a, b] 使得 a < l && b > r。 所以因为没有一种区间方式覆盖这个区间, 故在这个区间内一定会有一个点被作为起点。

    代码:

    #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
  • 相关阅读:
    重新整理 .net core 实践篇————配置系统之盟约[五]
    重新整理 .net core 实践篇————依赖注入应用之援军[四]
    重新整理 .net core 实践篇————依赖注入应用之生命法则[三]
    重新整理 .net core 实践篇————依赖注入应用[二]
    重新整理 .net core 实践篇————配置应用[一]
    spring cloud 学习笔记 客户端(本地)均衡负载(三)
    Leetcode之插入区间
    Leetcode之两棵二叉搜索树中的所有元素
    Leetcode之二叉树的层序遍历
    LeetCode之验证二叉搜索树
  • 原文地址:https://www.cnblogs.com/MingSD/p/10622170.html
Copyright © 2011-2022 走看看