zoukankan      html  css  js  c++  java
  • bzoj 5016 一个简单的询问

    THUWC 考了莫队(这个应该可以说吧)

    然而不会莫队,签到失败,所以找到了一道长得差不多的题写一写

    为什么这么长时间都没有发现这道题(半恼

    给你一个长度为N的序列ai,1≤i≤N和q组询问,每组询问读入l1,r1,l2,r2,需输出
     
    get(l,r,x)表示计算区间[l,r]中,数字x出现了多少次。
     
     
     
    sol:
     
    把一个询问拆成 4 个前缀询问,注意到 $sumlimits_{x=0}^{infty}get(l_1,r_1,x) cdot get(l_2,r_2,x) = sumlimits_{x=0}^{infty}get(1,r_1,x) cdot get(1,r_2,x) - sumlimits_{x=0}^{infty}get(1,l_1-1,x) cdot get(1,r_2,x) - sumlimits_{x=0}^{infty}get(1,r_1,x) cdot get(1,r_2 - 1,x) + sumlimits_{x=0}^{infty}get(1,l_1-1,x) cdot get(1,l_2-1,x)$
    然后每组询问就是一个二元组了(因为左端点都是 $1$) ,所以可以莫队,用两个 $cnt$ 数组记一下左边右边的每一个 $x$ 出现了多少次即可
    #include<bits/stdc++.h>
    #define LL long long
    using namespace std;
    inline int read()
    {
        int x = 0,f = 1;char ch = getchar();
        for(;!isdigit(ch);ch = getchar())if(ch == '-') f = -f;
        for(;isdigit(ch);ch = getchar())x = 10 * x + ch - '0';
        return x * f;
    }
    const int maxn = 50010;
    int n,a[maxn];
    int bl[maxn],tot,cntl[maxn],cntr[maxn];
    LL ans[maxn];
    struct Ques
    {
        int l,r,flag,pos;
        Ques(){}
        Ques(int _1,int _2,int _3,int _4): l(_1),r(_2),flag(_3),pos(_4){}
        bool operator < (const Ques &b)const{return (bl[l] == bl[b.l]) ? (r < b.r) : (bl[l] < bl[b.l]);}
    }qs[maxn << 2];
    int main()
    {
        n = read();
        for(int i=1;i<=n;i++)a[i] = read();
        int BLSIZE = sqrt(n);
        for(int i=1;i<=n;i++)bl[i] = i / BLSIZE;
        int q = read();
        for(int i=1;i<=q;i++)
        {
            int xl = read(),xr = read(),yl = read(),yr = read();
            qs[++tot] = Ques(xr,yr,1,i);
            if(xl > 1)qs[++tot] = Ques(xl - 1,yr,-1,i);
            if(yl > 1)qs[++tot] = Ques(xr,yl - 1,-1,i);
            if(xl > 1 && xr > 1)qs[++tot] = Ques(xl - 1,yl - 1,1,i);
        }
        sort(qs + 1,qs + tot + 1);
        int l = 0,r = 0;
        LL now = 0;
        for(int i=1;i<=tot;i++)
        {
            while(l < qs[i].l){l++;now += cntr[a[l]];cntl[a[l]]++;}
            while(r < qs[i].r){r++;now += cntl[a[r]];cntr[a[r]]++;}
            while(l > qs[i].l){cntl[a[l]]--;now -= cntr[a[l]];l--;}
            while(r > qs[i].r){cntr[a[r]]--;now -= cntl[a[r]];r--;}
            ans[qs[i].pos] += qs[i].flag * now; 
        }
        for(int i=1;i<=q;i++)cout << ans[i] << endl;
    }
    View Code
  • 相关阅读:
    【QT 学习笔记】 一、 VS2015+ QT环境安装
    Ubuntu16.04 + caffe + cuda 环境搭建
    【Caffe学习笔记】一 、环境安装 Caffe + cuda + windows10 + VS2015 安装笔记, win7也适用
    【CNN】 吴恩达课程中几种网络的比较
    【图像处理】二 高斯滤波及其加速方法
    【图像处理 】 一、OSTU分割法
    1028: C语言程序设计教程(第三版)课后习题8.2
    函数和带参的宏,从三个数中找出最大的数
    Last Defence (run time error)
    Penalty
  • 原文地址:https://www.cnblogs.com/Kong-Ruo/p/10326348.html
Copyright © 2011-2022 走看看