• P4867 Gty的二逼妹子序列


    $ color{#0066ff}{ 题目描述 }$

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

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

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

    (color{#0066ff}{输入格式})

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

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

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

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

    (color{#0066ff}{输出格式})

    对每个询问,单独输出一行,表示(s_l cdots s_r)中权值(in [a,b])的权值的种类数。

    (color{#0066ff}{输入样例})

    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
    

    (color{#0066ff}{输出样例})

    2
    0
    0
    2
    1
    1
    1
    0
    1
    2
    

    (color{#0066ff}{数据范围与提示})

    【样例的部分解释】

    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。

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

    5000ms / 30MB

    (color{#0066ff}{题解})

    一看题,这。。主席树啊

    再一看空间,30MB我去

    于是,这就是个莫队过百万的题了。。

    看来数据应该比较水把,于是写了个(O(nsqrt nlogn))的东西,然后T了。。。

    看来还是要与莫队齐平的复杂度的。。

    可以考虑对值域分块统计,因为值域也是只有n的,那么实际上复杂度与莫队同级, 就能过了

    // luogu-judger-enable-o2
    #include<bits/stdc++.h>
    #define LL long long
    LL in() {
    	char ch; LL x = 0, f = 1;
    	while(!isdigit(ch = getchar()))(ch == '-') && (f = -f);
    	for(x = ch ^ 48; isdigit(ch = getchar()); x = (x << 1) + (x << 3) + (ch ^ 48));
    	return x * f;
    }
    const int maxn = 1e6 + 10;
    int n, m, sqt;
    int ans[maxn], bel[maxn / 10], t[maxn / 10], k[maxn / 10];
    struct node {
    	int l, r, a, b, id;
    	friend bool operator < (const node &a, const node &b) {
    		if(bel[a.l] < bel[b.l]) return true;
    		if(bel[a.l] > bel[b.l]) return false;
    		return bel[a.l] & 1? a.r < b.r : a.r > b.r;
    	}
    }e[maxn];
    int a[maxn / 10];
    int id(int x) { return (x - 1) / sqt + 1; }
    void add(int now) {
    	t[now]++;
    	if(t[now] == 1) k[id(now)]++;
    }
    void del(int now) {
    	t[now]--;
    	if(!t[now]) k[id(now)]--;
    }
    int query(int a, int b) {
    	int tot = 0;
    	if(id(a) == id(b)) {
    		for(int i = a; i <= b; i++) tot += (t[i] > 0? 1 : 0);
    		return tot;
    	}
    	else {
    		for(int i = id(a) + 1; i <= id(b) - 1; i++) tot += k[i];
    		for(int i = a; i <= id(a) * sqt; i++) tot += (t[i] > 0? 1 : 0);
    		for(int i = (id(b) - 1) * sqt + 1; i <= b; i++) tot += (t[i] > 0? 1 : 0);
    		return tot;
    	}
    }
    int main() {
    	n = in(), m = in();
    	sqt = sqrt(n);
    	for(int i = 1; i <= n; i++) bel[i] = id(i), a[i] = in();
    	for(int i = 1; i <= m; i++) {
    		e[i].l = in(), e[i].r = in();
    		e[i].a = in(), e[i].b = in();
    		e[i].id = i;
    	}
    	int l = 1, r = 0;
    	std::sort(e + 1, e + m + 1);
    	for(int i = 1; i <= m; i++) {
    		while(l < e[i].l) del(a[l++]);
    		while(l > e[i].l) add(a[--l]);
    		while(r < e[i].r) add(a[++r]);
    		while(r > e[i].r) del(a[r--]);
    		ans[e[i].id] = query(e[i].a, e[i].b);
    	}
    	for(int i = 1; i <= m; i++) printf("%d
    ", ans[i]);
    	return 0;
    }
    
  • 相关阅读:
    欧拉回路
    2018 年 ACM-ICPC 焦作站现场赛感受
    3.1 基础-抛小球
    2.2 进阶-禁忌雷炎
    初学Java-循环输入直到文件结束
    1.1 基础-取近似值
    1.2 进阶-对称的二叉树
    LEETCODE
    算法
    算法
  • 原文地址:https://www.cnblogs.com/olinr/p/10463903.html
Copyright © 2020-2023  润新知