zoukankan      html  css  js  c++  java
  • P4396 [AHOI2013]作业 分块+莫队

    这个题正解是莫队+树状数组,但是我个人非常不喜欢树状数组这种东西,所以决定用分块来水这个题。直接在莫队维护信息的时候,维护单点同时维护块内信息就行了。

    莫队就是这几行核心代码:

    void add(int x)
    {
        ++f[bl[x]];//维护块
        ++cnt[x];//维护点
        if(cnt[x] == 1)
        g[bl[x]]++;
    }
    void del(int x)
    {
        --f[bl[x]];
        --cnt[x];
        if(!cnt[x])
        g[bl[x]]--;
    }
    void moqueue()
    {
        int l = 1,r = 0;
        duke(i,1,m)
        {
            while(l > G[i].l) add(s[--l]);
            while(l < G[i].l) del(s[l++]);
            while(r < G[i].r) add(s[++r]);
            while(r > G[i].r) del(s[r--]);
            work(G[i].a,G[i].b,i);
        }
    }

    剩下就是暴力了,说真的,这个作法真的暴力,但是就是能过。哈哈哈。

    题干:

    题目描述
    
    此时己是凌晨两点,刚刚做了Codeforces的小A掏出了英语试卷。英语作业其实不算多,一个小时刚好可以做完。然后是一个小时可以做完的数学作业,接下来是分别都是一个小时可以做完的化学,物理,语文......小A压力巨大。
    
    这是小A碰见了一道非常恶心的数学题,给定了一个长度为n的数列和若干个询问,每个询问是关于数列的区间表示数列的第1个数到第r个数),首先你要统计该区间内大于等于a,小于等于b的数的个数,其次是所有大于等于a,小于等于b的,且在该区间中出现过的数值的个数。
    
    小A望着那数万的数据规模几乎绝望,只能向大神您求救,请您帮帮他吧。
    输入输出格式
    输入格式:
    
    第一行n,m
    
    接下来n个数表示数列
    
    接下来m行,每行四个数l,r,a,b
    
    输出格式:
    
    输出m行,分别对应每个询问,输出两个数,分别为在1到i?这段区间中大小在[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

    代码:

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<ctime>
    #include<queue>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    #define duke(i,a,n) for(int i = a;i <= n;i++)
    #define lv(i,a,n) for(int i = a;i >= n;i--)
    #define clean(a) memset(a,0,sizeof(a))
    const int INF = 1 << 30;
    typedef long long ll;
    typedef double db;
    template <class T>
    void read(T &x)
    {
        char c;
        bool op = 0;
        while(c = getchar(), c < '0' || c > '9')
            if(c == '-') op = 1;
        x = c - '0';
        while(c = getchar(), c >= '0' && c <= '9')
            x = x * 10 + c - '0';
        if(op) x = -x;
    }
    template <class T>
    void write(T x)
    {
        if(x < 0) putchar('-'), x = -x;
        if(x >= 10) write(x / 10);
        putchar('0' + x % 10);
    }
    const int N=200010; 
    struct edge{
        int l,r,a,b;
        int ans1,ans2;
        int id;
    }G[N];
    int cnt[N];
    int bl[N];
    int blk;
    int n,m;
    int s[N];
    int f[N],g[N];
    bool cmp(edge x,edge y)
    {
        if(bl[x.l] != bl[y.l]) 
        return bl[x.l] < bl[y.l]; 
        else
        return x.r < y.r;
    }
    void add(int x)
    {
        ++f[bl[x]];
        ++cnt[x];
        if(cnt[x] == 1)
        g[bl[x]]++;
    }
    void del(int x)
    {
        --f[bl[x]];
        --cnt[x];
        if(!cnt[x])
        g[bl[x]]--;
    }
    void work(int l,int r,int x)
    {
        if(bl[l] == bl[r])
        {
            duke(i,l,r)
            {
                if(cnt[i])
                G[x].ans1 += cnt[i],G[x].ans2 ++;
            }
        }
        else
        {
            lv(i,bl[l] * blk - 1,l)
                if(cnt[i])
                    G[x].ans1 += cnt[i],G[x].ans2 ++;
            duke(i,bl[r] * blk - blk,r)
                if(cnt[i])
                    G[x].ans1 += cnt[i],G[x].ans2 ++;
            duke(i,bl[l] + 1,bl[r] - 1)
                G[x].ans1 += f[i],G[x].ans2 += g[i];
        }
    } 
    void moqueue()
    {
        int l = 1,r = 0;
        duke(i,1,m)
        {
            while(l > G[i].l) add(s[--l]);
            while(l < G[i].l) del(s[l++]);
            while(r < G[i].r) add(s[++r]);
            while(r > G[i].r) del(s[r--]);
            work(G[i].a,G[i].b,i);
        }
    }
    bool cmp2(edge a,edge b)
    {
        return a.id < b.id;
    }
    int main()
    {
        read(n);read(m); 
        duke(i,1,n)
        read(s[i]);
        blk = sqrt(n);
        duke(i,1,m)
        bl[i] = (i) / blk + 1;
        duke(i,1,m)
        {
            read(G[i].l);read(G[i].r);
            read(G[i].a);read(G[i].b);
            G[i].id = i; 
        }
        sort(G + 1,G + m + 1,cmp);
        moqueue();
        sort(G + 1,G + m + 1,cmp2);
        duke(i,1,m)
        {
            printf("%d %d
    ",G[i].ans1,G[i].ans2);
        }
        return 0;
    }
    /*
    3 4
    1 2 2
    1 2 1 3
    1 2 1 1
    1 3 1 3
    2 3 2 3
    */

    代码:

  • 相关阅读:
    Python range 函数 Python零基础入门教程
    Python eval 与 exec 函数的区别 Python零基础入门教程
    Python callable 函数 Python零基础入门教程
    Python bytes 函数 Python零基础入门教程
    Python ord 函数 Python零基础入门教程
    Python len函数 Python零基础入门教程
    第十二课 通过URL api拿到接送数据并做页面展示
    第十三课 axios请求数据
    网络编程学习路线计划
    erlang学习笔记本【不断更新】
  • 原文地址:https://www.cnblogs.com/DukeLv/p/9563076.html
Copyright © 2011-2022 走看看