zoukankan      html  css  js  c++  java
  • P4867 Gty的二逼妹子序列

    题目描述

    Autumn和Bakser又在研究Gty的妹子序列了!但他们遇到了一个难题。

    对于一段妹子们,他们想让你帮忙求出这之内美丽度∈[a,b]的妹子的美丽度的种类数。

    为了方便,我们规定妹子们的美丽度全都在[1,n]中。
    给定一个长度为n(1≤n≤100000)的正整数序列s(1≤si≤n),对于m(1≤m≤1000000)次询问l,r,a,b,每次输出sl⋯sr中,权值∈[a,b]的权值的种类数。

    输入输出格式

    输入格式:

    第一行包括两个整数n,m(1≤n≤100000,1≤m≤1000000),表示数列s中的元素数和询问数。

    第二行包括n个整数s1…sn(1≤si≤n)

    接下来m行,每行包括4个整数l,r,a,b(1≤l≤r≤n,1≤a≤b≤n),意义见题目描述。

    保证涉及的所有数在C++的int内。保证输入合法。

    输出格式:

    对每个询问,单独输出一行,表示sl⋯sr中权值∈[a,b]的权值的种类数。

    输入输出样例

    输入样例#1: 
    10 10
    4 4 5 1 4 1 5 1 2 1
    5 9 1 2
    3 4 7 9
    4 4 2 5
    2 3 4 7
    5 10 4 4
    3 9 1 1
    1 4 5 9
    8 9 3 3
    2 2 1 6
    8 9 1 4
    输出样例#1: 
    2
    0
    0
    2
    1
    1
    1
    0
    1
    2

    说明

    【样例的部分解释】

    5 9 1 2 子序列为4 1 5 1 2
    在[1,2]里的权值有1,1,2,有2种,因此答案为2。

    3 4 7 9
    子序列为5 1 在[7,9]里的权值有5,有1种,因此答案为1。

    4 4 2 5
    子序列为1
    没有权值在[2,5]中的,因此答案为0。

    2 3 4 7
    子序列为4 5
    权值在[4,7]中的有4,5,因此答案为2。

    建议使用输入/输出优化。

    Solution:

      本题根号过1e6的莫队,神奇~。

      本题需要求的是区间在值域范围内的种类数。

      我们直接离线做莫队,记录下每个块的左右边界(由于值域和操作区间范围都是$[1,n]$,所以分一次块就够了),统计每次指针变换后的每个块内元素出现的种类数,那么对于查询$(l,r,a,b)$,先把指针移到区间$[l,r]$(这里块按下标),累加$a$到$b$的所在块(这里块按值域)之间出现的种类数就好了。

      时间复杂度$O((n+m)sqrt n)$(我也不知道怎么能过~)。

    代码:

    /*Code by 520 -- 10.4*/
    #include<bits/stdc++.h>
    #define il inline
    #define ll long long
    #define RE register
    #define For(i,a,b) for(RE int (i)=(a);(i)<=(b);(i)++)
    #define Bor(i,a,b) for(RE int (i)=(b);(i)>=(a);(i)--)
    using namespace std;
    const int N=100005;
    int n,m,s[N],tot[N];
    int sum[5005],bl[N],ln[N],rn[N],ans[N*10];
    struct node{
        int l,r,a,b,id;
        bool operator < (const node &a) const {return bl[l]==bl[a.l]?r<a.r:l<a.l;}
    }q[N*10];
    
    int gi(){
        int a=0;char x=getchar();
        while(x<'0'||x>'9') x=getchar();
        while(x>='0'&&x<='9') a=(a<<3)+(a<<1)+(x^48),x=getchar();
        return a;
    }
    
    il void add(int v){if((++tot[v])==1)sum[bl[v]]++;}
    
    il void del(int v){if(!(--tot[v]))sum[bl[v]]--;}
    
    il int query(int a,int b){
        int l=bl[a],r=bl[b],res=0;
        for(RE int i=l+1;i<r;i++) res+=sum[i];
        if(l==r) For(i,a,b) res+=(tot[i]>0);
        else {
            For(i,a,rn[l]) res+=(tot[i]>0);
            For(i,ln[r],b) res+=(tot[i]>0);    
        }
        return res;
    }
    
    int main(){
        n=gi(),m=gi();int blo=sqrt(n);
        For(i,1,n) s[i]=gi(),bl[i]=(i-1)/blo+1;
        For(i,1,n) {
            rn[bl[i]]=i;
            if(!ln[bl[i]]) ln[bl[i]]=i;
        }
        For(i,1,m) q[i]=node{gi(),gi(),gi(),gi(),i};
        sort(q+1,q+m+1);
        for(RE int i=1,l=1,r=0;i<=m;i++){
            while(l<q[i].l) del(s[l]),l++;
            while(l>q[i].l) l--,add(s[l]);
            while(r<q[i].r) r++,add(s[r]);
            while(r>q[i].r) del(s[r]),r--;
            ans[q[i].id]=query(q[i].a,q[i].b);
        }
        For(i,1,m) printf("%d
    ",ans[i]); 
        return 0;
    }
  • 相关阅读:
    es6作用域
    es6函数的扩展
    input输入框ios上光标与placeholder、value不能对齐居中
    移动端input常用样式
    webpack安装遇到的坑
    错误类型
    滚动超出一定高度后,导航栏吸顶
    表单change()事件
    第二周学习进度
    第一周学习进度
  • 原文地址:https://www.cnblogs.com/five20/p/9792160.html
Copyright © 2011-2022 走看看