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\n",ans[i]);
    return 0;
}

原文地址:https://www.cnblogs.com/five20/p/9792160.html

时间: 2024-08-06 08:51:06

P4867 Gty的二逼妹子序列的相关文章

【BZOJ3809】Gty的二逼妹子序列

3809: Gty的二逼妹子序列 Time Limit: 80 Sec  Memory Limit: 28 MBSubmit: 1627  Solved: 481[Submit][Status][Discuss] Description Autumn和Bakser又在研究Gty的妹子序列了!但他们遇到了一个难题. 对于一段妹子们,他们想让你帮忙求出这之内美丽度∈[a,b]的妹子的美丽度的种类数. 为了方便,我们规定妹子们的美丽度全都在[1,n]中. 给定一个长度为n(1<=n<=100000)

【BZOJ 3809】 3809: Gty的二逼妹子序列 (莫队+分块)

3809: Gty的二逼妹子序列 Time Limit: 80 Sec  Memory Limit: 28 MBSubmit: 1728  Solved: 513 Description Autumn和Bakser又在研究Gty的妹子序列了!但他们遇到了一个难题. 对于一段妹子们,他们想让你帮忙求出这之内美丽度∈[a,b]的妹子的美丽度的种类数. 为了方便,我们规定妹子们的美丽度全都在[1,n]中. 给定一个长度为n(1<=n<=100000)的正整数序列s(1<=si<=n),对

Bzoj 3809: Gty的二逼妹子序列 莫队,分块

3809: Gty的二逼妹子序列 Time Limit: 35 Sec  Memory Limit: 28 MBSubmit: 868  Solved: 234[Submit][Status][Discuss] Description Autumn和Bakser又在研究Gty的妹子序列了!但他们遇到了一个难题. 对于一段妹子们,他们想让你帮忙求出这之内美丽度∈[a,b]的妹子的美丽度的种类数. 为了方便,我们规定妹子们的美丽度全都在[1,n]中. 给定一个长度为n(1<=n<=100000)的

【BZOJ-3809】Gty的二逼妹子序列 分块 + 莫队算法

3809: Gty的二逼妹子序列 Time Limit: 80 Sec  Memory Limit: 28 MBSubmit: 1072  Solved: 292[Submit][Status][Discuss] Description Autumn和Bakser又在研究Gty的妹子序列了!但他们遇到了一个难题. 对于一段妹子们,他们想让你帮忙求出这之内美丽度∈[a,b]的妹子的美丽度的种类数. 为了方便,我们规定妹子们的美丽度全都在[1,n]中. 给定一个长度为n(1<=n<=100000)

BZOJ-3809 Gty的二逼妹子序列

无修改的查询题,分块莫队+树状数组搞之.可这样貌似会Tle…… 于是不用树状数组,改成对权值进行分块,使查询的复杂度变成O(n^0.5),修改则是O(1).(原树状数组的复杂度:查询O(lgn),修改O(lgn)) #include <cstdlib> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <fstream>

BZOJ3809 Gty的二逼妹子序列

终于做到了BZ上最新的题2333 这题一看就是...莫队,然后查询的时候树状数组. 结果T了,诶诶诶诶%>_<%,怎么可以这样! 另寻他法:hzwer的分块 恩恩,就是把颜色分成n块,然后单词修改O(1),单词查询O(n / sz + 2 * sz) sz = sqrt(n / 2)的时候最好(理论上),实际上sz = sqrt(n)一点都不慢....要不要下次试试sz = log(n) 1 /**************************************************

【莫队算法】【权值分块】bzoj3809 Gty的二逼妹子序列

如题. #include<cstdio> #include<algorithm> #include<cmath> using namespace std; int Num,CH[12],f,c; inline void R(int &x){ c=0;f=1; for(;c<'0'||c>'9';c=getchar())if(c=='-')f=-1; for(x=0;c>='0'&&c<='9';c=getchar())(x

【BZOJ】3809: Gty的二逼妹子序列

http://www.lydsy.com/JudgeOnline/problem.php?id=3809 题意:n个元素(1<=n<=100000)每个元素有一权值<=n.q个询问,1<=q<=1000000,每次询问区间[l, r]的权值在区间[a, b]的种类数.时限35s... #include <cstdio> #include <cstring> #include <cmath> #include <string> #

bzoj 3809 Gty的二逼妹子序列 —— 莫队+分块

题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3809 据说一开始应该想到莫队+树状数组,然而我想的却是莫队+权值线段树... 如果用权值线段树,则修改和查询都是 O(logn),总复杂度 O(n√nlogn),艰难...(而且仔细一看空间有点卡?) 看了TJ,才发现权值也可以分块,则查询 O(√n) 但修改 O(1),就可以过咯~ 代码如下: #include<iostream> #include<cstdio> #inc