zoukankan      html  css  js  c++  java
  • P3567 [POI2014]KUR-Couriers

    给出元素,求区间次数次数大于一半的数字
    传送门

    莫队先统计数字个数,然后用随机化随即下标,因为出现次数大于区间一半,那么有大于(frac{1}{2})的概率能找到这个数字
    进行随机化20次即可.
    时间复杂度(O(20nsqrt n)),开个O(2)顺利过去

    #include <bits/stdc++.h>
    #define ll long long
    #define ld long double
    #define CASE int Kase = 0; cin >> Kase; for(int kase = 1; kase <= Kase; kase++)
    using namespace std;
    template<typename T = long long> inline T read() {
        T s = 0, f = 1; char ch = getchar();
        while(!isdigit(ch)) {if(ch == '-') f = -1; ch = getchar();}
        while(isdigit(ch)) {s = (s << 3) + (s << 1) + ch - 48; ch = getchar();} 
        return s * f;
    }
    #ifdef ONLINE_JUDGE
    #define qaq(...) ;
    #define qwq(c) ;
    #else
    #define qwq(a, b) for_each(a, b, [=](int x){cerr << x << " ";}), cerr << std::endl
    template <typename... T> void qaq(const T &...args) {
        auto &os = std::cerr;
        (void)(int[]){(os << args << " ", 0)...};
        os << std::endl;
    }
    #endif
    const int N = 5e5 + 5, M = 1e6 + 5, MOD = 1e9 + 7, CM = 998244353, INF = 0x3f3f3f3f; const ll linf = 0x7f7f7f7f7f7f7f7f;
    struct Query{
        int l, r, id;
    } que[N];
    int a[N], bl[N];
    bool cmp(Query a, Query b){
        return (bl[a.l] ^ bl[b.l]) ? bl[a.l] < bl[b.l] : ((bl[a.l] & 1) ? a.r < b.r : a.r > b.r);
    }
    int l = 1, r = 0, now, Ans[N];
    int cnt[N], nowlen = 0;
    inline void add(int x) {
        ++cnt[a[x]];
        // if(cnt[a[x]] > (nowlen / 2)) now = a[x];
    }
    inline void del(int x) {
        --cnt[a[x]];
        // if(cnt[a[x]] > (nowlen / 2)) now = a[x];
    }
    template<typename T>
    inline T rand(T a, T b){
        return rand() % (b - a + 1) + a;
    }
    void solve(int kase){
        int n = read(), q = read();
        for(int i = 1; i <= n; i++) a[i] = read();
        int unt = sqrt(n);
        for(int i = 1; i <= n; i++) bl[i] = (i - 1) / unt + 1;
        for(int i = 1; i <= q; i++) {
            que[i].id = i; que[i].l = read(), que[i].r = read();
        }
        sort(que + 1, que + q + 1, cmp);
        for(int i = 1; i <= q; i++) {
            nowlen = que[i].r - que[i].l + 1;
            while(l < que[i].l) del(l++);
            while(l > que[i].l) add(--l);
            while(r < que[i].r) add(++r);
            while(r > que[i].r) del(r--);
            now = 0;
            for(int j = 1; j <= 20; j++) {
                int pos = rand(que[i].l, que[i].r);
                if(cnt[a[pos]] > nowlen / 2) {
                    now = a[pos];
                    break;
                } 
            }
            Ans[que[i].id] = now;
        }
        for(int i = 1; i <= q; i++) {
            printf("%d
    ", Ans[i]);
        }
    }
    const bool ISFILE = 0, DUO = 0;
    int main(){
        srand(time(NULL));
        clock_t start, finish; start = clock();
        if(ISFILE) freopen("/Users/i/Desktop/practice/in.txt", "r", stdin);
        if(DUO) {CASE solve(kase);} else solve(1);
        finish = clock(); 
        qaq("
    Time:", (double)(finish - start) / CLOCKS_PER_SEC * 1000, "ms
    ");
        return 0;
    }
    

    对于一个区间任意排序,然后进行划分,求最小划分次数使得每个子区间都是好序列。
    求出出现次数最大的那个数字,也就是大于(lceilfrac{n}{2} ceil)
    然后把剩下的数字和出现次数出现最多的数字放一组,然后剩下的数字都是相同的数字,这些数字一个数字一组。
    然后区间求出现次数超过(lceilfrac{n}{2} ceil)的数字可以用二分

    int getnum(int x, int l, int r){
        int lpos = lower_bound(v[x].begin(), v[x].end(), l) - v[x].begin();
        int rpos = upper_bound(v[x].begin(), v[x].end(), r) - v[x].begin() - 1;
        return max(0, rpos - lpos + 1);
    }
    
    #include <bits/stdc++.h>
    #define ll long long
    #define ld long double
    #define CASE int Kase = 0; cin >> Kase; for(int kase = 1; kase <= Kase; kase++)
    using namespace std;
    template<typename T = long long> inline T read() {
        T s = 0, f = 1; char ch = getchar();
        while(!isdigit(ch)) {if(ch == '-') f = -1; ch = getchar();}
        while(isdigit(ch)) {s = (s << 3) + (s << 1) + ch - 48; ch = getchar();} 
        return s * f;
    }
    #ifdef ONLINE_JUDGE
    #define qaq(...) ;
    #define qwq(c) ;
    #else
    #define qwq(a, b) for_each(a, b, [=](int x){cerr << x << " ";}), cerr << std::endl
    template <typename... T> void qaq(const T &...args) {
        auto &os = std::cerr;
        (void)(int[]){(os << args << " ", 0)...};
        os << std::endl;
    }
    #endif
    const int N = 5e5 + 5, M = 1e6 + 5, MOD = 1e9 + 7, CM = 998244353, INF = 0x3f3f3f3f; const ll linf = 0x7f7f7f7f7f7f7f7f;
    int a[N], Ans[N];
    int l = 1, r;
    std::vector<int> v[N];
    int getnum(int x, int l, int r){
        int lpos = lower_bound(v[x].begin(), v[x].end(), l) - v[x].begin();
        int rpos = upper_bound(v[x].begin(), v[x].end(), r) - v[x].begin() - 1;
        return max(0, rpos - lpos + 1);
    }
    unsigned seed = std::chrono::system_clock::now().time_since_epoch().count();
    mt19937 rand_num(seed);
    int getmaxnum(int l, int r){
        int len = r - l + 1;
        for(int i = 1; i <= 30; i++) {
            uniform_int_distribution<int> dist(l, r);  // 给定范围
            int pos = dist(rand_num);
            if(getnum(a[pos], l, r) > (len + 1) / 2) return a[pos];
        }
        return 0;
    }
    int cal(int l, int r){
        int max_num = getmaxnum(l, r);
        if(max_num == 0) return 1; // 出現n/2次
        int num_times = getnum(max_num, l, r);
        int remind = (r - l + 1) - num_times;
        int match = remind + 1;
        if((remind + match) & 1) return 1 + num_times - match;
        else {
            match = remind;
            return 1 + num_times - match;
        }
    }
    void solve(int kase){
        int n = read(), q = read();
        for(int i = 1; i <= n; i++) a[i] = read(), v[a[i]].push_back(i);
        for(int i = 1; i <= q; i++) {
            int l = read(), r = read();
            printf("%d
    ", cal(l, r));
        }
    }
    const bool ISFILE = 0, DUO = 0;
    int main(){
        clock_t start, finish; start = clock();
        if(ISFILE) freopen("/Users/i/Desktop/practice/in.txt", "r", stdin);
        if(DUO) {CASE solve(kase);} else solve(1);
        finish = clock(); 
        qaq("
    Time:", (double)(finish - start) / CLOCKS_PER_SEC * 1000, "ms
    ");
        return 0;
    }
    
    I‘m Stein, welcome to my blog
  • 相关阅读:
    定义函数
    变量与常量
    字符串与格式化
    字符串与编码
    字符编码
    元组-tuple
    列表-list
    分支和循环
    润乾配置连接kingbase(金仓)数据库
    润乾报表在proxool应用下的数据源配置
  • 原文地址:https://www.cnblogs.com/Emcikem/p/14681132.html
Copyright © 2011-2022 走看看