• Luogu4688 [Ynoi2016]掉进兔子洞 【莫队,bitset】


    题目链接:洛谷

    我们知道要求的是([l_1,r_1],[l_2,r_2],[l_3,r_3])的可重集取交的大小,肯定是要用bitset的,那怎么做可重集呢?

    那就是要稍微动点手脚,首先在离散化的时候,将(a_x)设为(leq a_x)的数的个数,然后再插入一个数的时候,将(a_x-cnt_{a_x})设为1,删除的时候设为0,然后直接取交就可以了。正确性比较显然。

    还有一个问题就是如何存下(100000*100000)的bitset,那肯定是存不下的,所以把询问分成3部分,然后每块分别做就可以用时间换空间了。

    #include<bits/stdc++.h>
    #define Rint register int
    using namespace std;
    typedef long long LL;
    const int N = 100010, M = 33340;
    int n, m, _n, len, a[N], val[N], cnt[N], ql, qr, tmp[M];
    bitset<N> ans[M], now;
    struct Query {
    	int l, r, id;
    	inline bool operator < (const Query &o) const {
    		if(l / len != o.l / len) return l / len < o.l / len;
    		if(l / len & 1) return r > o.r;
    		return r < o.r;
    	}
    } que[N];
    inline void add(int x){++ cnt[x]; now[x - cnt[x]] = 1;}
    inline void del(int x){now[x - cnt[x]] = 0; -- cnt[x];}
    inline void solve(int m){
    	for(Rint i = 1;i <= n;i ++) cnt[i] = 0;
    	for(Rint i = 1;i <= m;i ++) ans[i].set(), tmp[i] = 0; now.reset(); ql = 1; qr = 0;
    	for(Rint i = 1;i <= 3 * m;i ++) scanf("%d%d", &que[i].l, &que[i].r), tmp[que[i].id = (i + 2) / 3] += que[i].r - que[i].l + 1;
    	sort(que + 1, que + 3 * m + 1);
    	for(Rint i = 1;i <= 3 * m;i ++){
    		while(ql > que[i].l) add(a[-- ql]);
    		while(qr < que[i].r) add(a[++ qr]);
    		while(qr > que[i].r) del(a[qr --]);
    		while(ql < que[i].l) del(a[ql ++]);
    		ans[que[i].id] &= now;
    	}
    	for(Rint i = 1;i <= m;i ++) printf("%d
    ", tmp[i] - 3 * ans[i].count());
    }
    int main(){
    	scanf("%d%d", &n, &m); len = sqrt(n);
    	for(Rint i = 1;i <= n;i ++) scanf("%d", a + i), val[i] = a[i];
    	sort(val + 1, val + n + 1);
    	_n = unique(val + 1, val + n + 1) - val - 1;
    	for(Rint i = 1;i <= n;i ++) a[i] = lower_bound(val + 1, val + _n + 1, a[i]) - val;
    	for(Rint i = 1;i <= _n;i ++) val[i] = 0;
    	for(Rint i = 1;i <= n;i ++) ++ val[a[i]];
    	for(Rint i = 1;i <= _n;i ++) val[i] += val[i - 1];
    	for(Rint i = 1;i <= n;i ++) a[i] = val[a[i]];
    	solve(m / 3); solve((m + 1) / 3); solve((m + 2) / 3);
    }
    
  • 相关阅读:
    简单的一个php验证登陆代码
    目标,信念,坚强,淡定,团队
    linux下安装redis及PHP扩展应用
    mysql 命令行 隔离级别
    数据库事务的隔离级别
    mysql 乐观锁和悲观锁
    SpringBoot跨域问题CORS解决
    Oracle SQL题目及其解答(学生、课程、成绩、教师)
    SpringCloud学习2-eureka
    SpringCloud学习1-概述
  • 原文地址:https://www.cnblogs.com/AThousandMoons/p/11623510.html
Copyright © 2020-2023  润新知