zoukankan      html  css  js  c++  java
  • POJ

    筛法+划分树。

    枚举因子,类似筛法计算因子数量,复杂度为n/2 + n/3 + ... + n/n ≈ O(nlogn)。

    值域已知,只有删除操作,寻找kth,用划分树就好了O(nlogn)。二分+树状数组也可以,只是复杂度多乘一个logn。

    /*********************************************************
    *            ------------------                          *
    *   author AbyssalFish                                   *
    **********************************************************/
    #include<cstdio>
    #include<iostream>
    #include<string>
    #include<cstring>
    #include<queue>
    #include<vector>
    #include<stack>
    #include<vector>
    #include<map>
    #include<set>
    #include<algorithm>
    #include<cmath>
    #include<numeric>
    using namespace std;
    
    const int MAX_SIZE = 1<<20, MAX_N = 5e5, LEN = 11;
    
    int s[MAX_SIZE];
    int N, K;
    #define para int o = 1, int l = 0,int r = N-1
    #define Tvar int mid = (l+r)>>1, lc = (o<<1), rc = (o<<1|1);
    #define lsn lc, l, mid
    #define rsn rc, mid+1, r
    
    void build(para)
    {
        s[o] = r-l+1;
        if(l == r) return;
        else {
            Tvar
            build(lsn);
            build(rsn);
        }
    }
    
    int q_modify(int k, para)
    {
        s[o]--;
        if(l == r){
            return l;
        }
        else {
            Tvar
            if(k<=s[lc]) return q_modify(k, lsn);
            return q_modify(k-s[lc], rsn);
        }
    }
    
    char name[MAX_N][LEN];
    int card[MAX_N];
    
    int Fp[MAX_N+1];
    
    
    
    #define LOCAL
    int main()
    {
    #ifdef LOCAL
        freopen("in.txt","r",stdin);
    #endif
        //cout<<(1<<20);//ceil(log2(5e5)+1);
        scanf("%d%d",&N,&K);
        for(int i = 2; i <= N; i++){
            for(int j = i; j <= N; j += i){
                Fp[j]++;
            }
        }
        int tar = 1;
        for(int i = 2; i <= N; i++){
            if(Fp[tar] < Fp[i]) tar = i;
        }
        for(int i = 0; i < N; i++) scanf("%s%d", name[i], card+i);
        build();
        int pos , kth = K-1, mn = N-tar;
        for(int n = N; n-- > mn; ){
            pos = q_modify(kth+1);//位置下标从必须开始0,这样才方便取模
            if(n){
                if(card[pos] > 0) card[pos]--; //可以看作往后移动一下,然后把kth去掉
                kth = (card[pos]+kth)%n;
                if(kth < 0) kth += n;
            }
        }
        printf("%s %d
    ", name[pos], Fp[tar]+1);
        return 0;
    }
    线段树

    12.8更新~

    其实树状数组也可以logN的找到kth的, 就像猜数字一样不断缩小范围。

    /*********************************************************
    *            ------------------                          *
    *   author AbyssalFish                                   *
    **********************************************************/
    #include<cstdio>
    #include<iostream>
    #include<string>
    #include<cstring>
    #include<queue>
    #include<vector>
    #include<stack>
    #include<vector>
    #include<map>
    #include<set>
    #include<algorithm>
    #include<cmath>
    #include<numeric>
    using namespace std;
    
    const int MAX_N = 5e5+1, LEN = 11;
    
    char name[MAX_N][LEN];
    int card[MAX_N];
    
    
    int N, K;
    
    int C[MAX_N];
    
    int q_Kth(int k)
    {
        int p = 0, c = 0;
        for(int i = 19; i >= 0; i--){
            p += 1<<i;
            (p >= N || c + C[p] >= k)? p -= 1<<i : c += C[p];
        }
        return p+1;
    }
    
    void sub(int x)
    {
        while(x <= N){
            C[x]--; x += x&-x;
        }
    }
    
    
    
    int Fp[MAX_N+1];
    
    
    
    //#define LOCAL
    int main()
    {
    #ifdef LOCAL
        freopen("in.txt","r",stdin);
    #endif
        //cout<<(1<<20);//ceil(log2(5e5)+1);
        scanf("%d%d",&N,&K);
        for(int i = 2; i <= N; i++){
            for(int j = i; j <= N; j += i){
                Fp[j]++;
            }
        }
        int tar = 1;
        for(int i = 2; i <= N; i++){
            if(Fp[tar] < Fp[i]) tar = i;
        }
        for(int i = 0; i < N; i++) scanf("%s%d", name[i], card+i);
        for(int i = 1; i <= N; i++) {
            C[i] = i&-i;
        }
        int pos , k = K-1, mn = N-tar;
        for(int n = N; n-- > mn; ){
            pos = q_Kth(k+1)-1; sub(pos+1);
            if(n){
                if(card[pos] > 0) card[pos]--;
                k = (card[pos]+k)%n;
                if(k < 0) k += n;
            }
        }
        printf("%s %d
    ", name[pos], Fp[tar]+1);
        return 0;
    }
    树状数组
  • 相关阅读:
    AHK的OnMessage
    VBA7种文档遍历法
    Excel VBA 找出选定范围不重复值和重复值
    Excel图片调整大小
    Excel信息提取之二
    Excel不同工作簿之间提取信息
    VBA7种遍历方法
    Exce信息提取
    php笔记之文件载入和异常处理
    php笔记之流程控制
  • 原文地址:https://www.cnblogs.com/jerryRey/p/4977437.html
Copyright © 2011-2022 走看看