zoukankan      html  css  js  c++  java
  • 2011-2012 Winter Petrozavodsk Camp, Andrew Stankevich Contest 41 (ASC 41)——莫队算法——Data Mining

    /*
    莫队算法是离线算法,用来解决已知l,r问你l,r里面值的问题
    对块进行排序,后面的块通过前面的块左移右移得到,所以可能有的情况能得到O(1)或者较低的复杂度
    排序的时候除以跟好n(?)
    本题题意:从l到r区间内问有多少个不同的数,询问很多
    
    
    
    
    
    
    */
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<map>
    #include<cmath>
    #include<vector>
    using namespace std;
    
    const int MAX = 2000000 + 10;
    int a[MAX];
    map <int, int> table;
    int res[MAX];
    int ans[MAX];
    int n, m;
    vector<int> G[MAX];
    int unit;
    
    struct edge{
        int l, r, id;
    }b[MAX];
    
    bool cmp(edge i, edge j){
        if(i.l/unit == j.l/unit){
            return i.r/unit < j.r/unit;
        }
        return i.l/unit < j.l/unit;
    }
    
    
    
    void modui()
    {
        sort(b + 1, b + m + 1, cmp);
        memset(res, 0, sizeof(res));
        int l = 1, r = 0, ret = 0;
        for(int i = 1; i <= m; i++){
            while(l < b[i].l){
                res[a[l]] --;
                if(res[a[l]] == 0)
                    ret--;
                l++;
            }//l不是,那么数少一,如果该数目变成0,说明原来加了该数,总数减少1
            while(l > b[i].l){
                res[a[--l]]++;
                if(res[a[l]] == 1)
                    ret++;
            }//l是,那么l-1也是(l>b[i].l)说明l少1可能就是临界值,如果变成1,说明多了一个数
            while( r < b[i].r){
                res[a[++r]]++;
                if(res[a[r]] == 1) 
                    ret++;
            }
            while( r > b[i].r){
                res[a[r]] --;
                if(res[a[r]] == 0)
                    ret--;
                r--;
            }
           ans[b[i].id] = ret;
           //块的编号
        }
        for(int i = 1; i <= m ; i++)
            printf("%d
    ",ans[i]);
    }
    
    int main()
    {
    	freopen ("data.in", "r", stdin);
    	freopen ("data.out", "w", stdout);
    
        while(~scanf("%d", &n)){
            int num = 0;
    
            table.clear();
            for(int i = 1; i <= n ; i++)
                G[i].clear();
            for(int i = 1; i <= n ;i++){
                scanf("%d", &a[i]);
            a[i] = table[a[i]] ? table[a[i]] : table[a[i]] = ++num ;//离散化
            //如果table[a[i]] 有值,那么a[i] = table[a[i]],相当于编号,如果没有,那么向后推
            G[a[i]].push_back(i);//记录值为a[i]的各个数的位置
            }
            unit = (int)sqrt(1.0*n);
            scanf("%d", &m);
            int l, r;
            for(int i = 1; i <= m; i++){
                scanf("%d%d", &l, &r);
                r = l + r - 1;
            int pos = lower_bound(G[a[r]].begin(), G[a[r]].end(), l) - G[a[r]].begin();//二分得到r再l的右边最先出现过的位置
            r = G[a[r]][pos]  ;
            b[i].l = l; b[i].r = r; b[i].id = i;
            }
            modui();
        }
        return 0;
    }
                
    

      

  • 相关阅读:
    BootstrapTable表格数据左右移动功能遇到的问题(数据左右移动,列表拖拽排序,模糊查询列表数据定位)
    MVC校验
    线程
    验证码
    PublicLogic
    进程
    请求处理过程
    上传组件
    委托
    Global全局应用程序类
  • 原文地址:https://www.cnblogs.com/zero-begin/p/4652484.html
Copyright © 2011-2022 走看看