zoukankan      html  css  js  c++  java
  • P4396 [AHOI2013]作业

    题目描述

    此时己是凌晨两点,刚刚做了Codeforces的小A掏出了英语试卷。英语作业其实不算多,一个小时刚好可以做完。然后是一个小时可以做完的数学作业,接下来是分别都是一个小时可以做完的化学,物理,语文......小A压力巨大。

    这是小A碰见了一道非常恶心的数学题,给定了一个长度为n的数列和若干个询问,每个询问是关于数列的区间表示数列的第l个数到第r个数),首先你要统计该区间内大于等于a,小于等于b的数的个数,其次是所有大于等于a,小于等于b的,且在该区间中出现过的数值的个数。

    小A望着那数万的数据规模几乎绝望,只能向大神您求救,请您帮帮他吧。

    输入输出格式

    输入格式:

    第一行n,m

    接下来n个数表示数列

    接下来m行,每行四个数l,r,a,b

    输出格式:

    输出m行,分别对应每个询问,输出两个数,分别为在l到r这段区间中大小在[a,b]中的数的个数,以及大于等于a,小于等于b的,且在该区间中出现过的数值的个数(具体可以参考样例)。

    输入输出样例

    输入样例#1: 
    3 4
    1 2 2
    1 2 1 3
    1 2 1 1
    1 3 1 3
    2 3 2 3
    输出样例#1: 
    2 2
    1 1
    3 2
    2 1

    说明

    N<=100000,M<=100000

    Solution:

      本题是上题妹子序列的加强版?反正还是莫队。

      第二问就是上题的询问(只不过数据弱化了),第一问也很简单,只需要在分块时多维护一下值域范围内的数的个数,其它就是一些细节问题的处理了。

    代码:

    /*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,a[N],ln[N],rn[N];
    int sum[5005],ppx[5005],c[N],bl[N],ans[N][2];
    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];
    
    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){ppx[bl[v]]++,sum[bl[v]]+=((++c[v])==1);}
    
    il void del(int v){ppx[bl[v]]--,sum[bl[v]]-=((--c[v])==0);}
    
    il void query(node x){
        int l=bl[x.a],r=bl[x.b],res1=0,res2=0;
        for(RE int i=l+1;i<r;i++) res1+=ppx[i],res2+=sum[i];
        if(l==r) For(i,x.a,x.b) res1+=c[i],res2+=(c[i]>0);
        else {
            For(i,x.a,rn[l]) res1+=c[i],res2+=(c[i]>0);
            For(i,ln[r],x.b) res1+=c[i],res2+=(c[i]>0);
        }
        ans[x.id][0]=res1,ans[x.id][1]=res2;
    }
    
    int main(){
        n=gi(),m=gi(); int blo=sqrt(n);
        For(i,1,n) a[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(a[l]),++l;
            while(l>q[i].l) --l,add(a[l]);
            while(r<q[i].r) ++r,add(a[r]);
            while(r>q[i].r) del(a[r]),--r;
            query(q[i]);
        }
        For(i,1,m) printf("%d %d
    ",ans[i][0],ans[i][1]);
        return 0;
    }
  • 相关阅读:
    VIS识别系统
    浅谈web标准、可用性、可访问性
    CSS中IE6、7和火狐对margin、padding的兼容性解析【转】
    css 之 clearfix ——清除浮动
    总结写DIV+CSS时常见的小问题
    优化JavaScript脚本的性能总结
    QUEUE C语言实现
    mtlab设置plot画图函数y轴的显示范围
    matlab中基本操作(对已知数组16进制转化为10进制)
    queue 的C语言实现
  • 原文地址:https://www.cnblogs.com/five20/p/9792231.html
Copyright © 2011-2022 走看看