zoukankan      html  css  js  c++  java
  • 【洛谷SP3267】DQUERY

    题目链接

    DQUERY - D-query

    题目描述

    Given a sequence of (n) numbers (a_{1},a_{2},...,a_{n}) and a number of d-queries. A d-query is a pair ((i,j)) ((1 le i le j le n)). For each d-query ((i,j)), you have to return the number of distinct elements in the subsequence (a_{i},a _{i+1},...,a_{j}).

    输入格式

    • Line 1: (n) ((1 le n le 30000)).
    • Line 2: n numbers (a_{1},a_{2},...,a_{n}) ((1 le a_{i} le 10^{6})).
    • Line 3: (q) ((1 le q le 200000)), the number of d-queries.
    • In the next (q) lines, each line contains (2) numbers (i),(j) representing a d-query ((1 le i le j le n)).

    输出格式

    • For each d-query ((i,j)), print the number of distinct elements in the subsequence (a_{i},a_{i+1},...,a_{j}) in a single line.

    题意翻译

    给出一个长度为(n)的数列,(a_{1},a_{2},...,a_{n}),有(q)个询问,每个询问给出数对((i,j)),需要你给出(a_{i},a_{i+1},...,a_{j})这一段中有多少不同的数字

    样例输入

    5
    1 1 2 1 3
    3
    1 5
    2 4
    3 5
    

    样例输出

    3
    2
    3
    

    题解

    题意:看翻译吧。。。
    这是一道莫队板题。(明显的)
    本人其实也是刚学莫队,对于莫队可能也有一些误解,如果有不正确的解释请各位大佬指出。
    因为做到一个据说需要莫队的题目,所以开始学习莫队了。
    原本以为莫队是很难的,看了别人的博客后感觉看不懂(优雅的暴力?),然后开始看别人写的代码和板题。
    然后。。。
    这真TM是优雅的暴力!!!
    好了,吐槽结束,其实大家只要知道莫队其实本质是暴力,只不过用特殊的方法排了个序而已。
    我们考虑这样一种暴力,用(cnt[])(l,r)维护(l)(r)区间内各个数字的个数(因为数字的大小最大为(10^6)),并且维护一个(ans)值,然后我们移动(l)(r)的时候可以快速地维护这个数组和(ans)值了。
    但是我们可以发现直接这样维护的话时间复杂度还是(O(n^2))的。
    那么我们考虑离线操作,对输入的询问排个序。
    如果我们按照询问的(l)值从小到大排序,使维护的区间的(l)只会往右移动,那么可能可以减少一点时间,但是想一下就会发现这种方法是可能被卡成(O(n^2))的,比如询问按照(l)排序后(r)的值是一大一小,那么每次询问的时间复杂度都是(O(n))
    那么我们开始讲莫队,莫队就是利用了分块的思想,我们把询问中(frac {l}{sqrt{n}})相同的数分为一组(这里分块的大小是(sqrt{n}),一般来说随机数据的话区(sqrt{n})会比较好,但是不同的题目分块的大小也可以不同)
    然后在同一组内的询问,我们按照询问的(r)值从小到大排序。
    这样你就会发现在每(sqrt{n})次询问内,因为每个区间(r)值是从小到大排序的,所以你区间移动的距离最多为(n+sqrt{n}*sqrt{n})(近似为(n)),那么莫队的时间复杂度就是(O(nsqrt{n}))
    上代码:

    #include<bits/stdc++.h>
    using namespace std;
    int n,m;
    int a[30009];
    struct aa{
        int l,r,x,ans;
    }p[200009];
    int sq;
    bool cmp(aa x,aa y){//按照莫队算法排序
        if(x.l/sq<y.l/sq) return 1;
        if(x.l/sq>y.l/sq) return 0;
        return x.r<y.r;
    }
    int cnt[1000009];
    bool cmpp(aa x,aa y){return x.x<y.x;}
    int main(){
        scanf("%d",&n);
        sq=sqrt(n);
        for(int j=1;j<=n;j++)
            scanf("%d",&a[j]);
        scanf("%d",&m);
        for(int j=1;j<=m;j++){
            scanf("%d%d",&p[j].l,&p[j].r);
            p[j].x=j;//因为最后输出要按输入的顺序输出,所以这里记录输入的顺序
        }
        sort(p+1,p+m+1,cmp);
        int ll=1,rr=1,ss=1;
        cnt[a[1]]=1;
        for(int j=1;j<=m;j++){
            while(rr<p[j].r){
                rr++;
                cnt[a[rr]]++;
                if(cnt[a[rr]]==1) ss++;
            }
            while(ll>p[j].l){
                ll--;
                cnt[a[ll]]++;
                if(cnt[a[ll]]==1) ss++;
            }
            while(rr>p[j].r){
                cnt[a[rr]]--;
                if(cnt[a[rr]]==0) ss--;
                rr--;
            }
            while(ll<p[j].l){
                cnt[a[ll]]--;
                if(cnt[a[ll]]==0) ss--;
                ll++;
            }
            p[j].ans=ss;//记录答案
        }
        sort(p+1,p+m+1,cmpp);
        for(int j=1;j<=m;j++)
            printf("%d
    ",p[j].ans);
        return 0;
    }
    
  • 相关阅读:
    AngularJS 包含HTML文件
    AngularJS 验证
    AngularJS html+DOM+ng-click事件
    表格边框css
    Ubantu下面命令听歌(豆瓣fm)
    AngularJS $http
    AngularJS过滤器
    Python-注册
    Python之内置函数
    生成手机号码代码
  • 原文地址:https://www.cnblogs.com/linjiale/p/11761445.html
Copyright © 2011-2022 走看看