luogu P4688 [Ynoi2016]掉进兔子洞 bitset 莫队

题目链接

luogu P4688 [Ynoi2016]掉进兔子洞

题解

莫队维护bitset区间交个数

代码

// luogu-judger-enable-o2
#include<cmath>
#include<bitset>
#include<cstdio>
#include<cstring>
#include<algorithm>
inline int read() {
    int x = 0,f = 1;
    char c = getchar();
    while(c < '0' || c > '9') {if(c == '-')f = -1 ; c = getchar(); }
    while(c <= '9' && c >= '0') x = x * 10 + c - '0', c = getchar();
    return x * f;
}
const int whattt = 20001;
const int maxn = 100007;
int a[maxn],bel[maxn],b[maxn];
int l1[maxn],r1[maxn],l2[maxn],r2[maxn],l3[maxn],r3[maxn];
int sum[maxn];
int n,m,k;
struct Que {
    int l,r,id;
     Que(int l = 0,int r = 0,int id = 0) :l (l),r (r),id (id){};
     bool operator < (const Que & a) const {
            if(bel[l] == bel[a.l]) return r < a.r;
            return bel[l] < bel[a.l];
    }
} q[33334 * 3 + 7];
std::bitset<100000> F[whattt + 7],f;
bool mark[33334 + 7];
int len;
int cnt[maxn],c[whattt * 3 + 7];
void update(int k,int ty) {
    k = a[k]; cnt[k] += ty;
    if(ty == 1) f[k + cnt[k] - 2] = 1;
    else f[k + cnt[k] - 1] = 0;
}
void solve() {
    memset(mark,0,sizeof mark);
    memset(cnt,0,sizeof(cnt));
    std::sort(q + 1,q + len + 1);
    int l = 1,r = 0;
    f.reset();
    for(int i = 1;i <= len;++ i) {
        while(r < q[i].r) update(++ r,1);
        while(r > q[i].r) update(r --,-1);
        while(l < q[i].l) update(l ++,-1);
        while(l > q[i].l) update(-- l,1);
        if(mark[q[i].id])F[q[i].id] &= f,c[q[i].id] = F[q[i].id].count();
        else F[q[i].id] = f,mark[q[i].id] = 1;
    }
}
int main() {
    //freopen("xp1.in","r",stdin);
    n = read(),m = read();
    k = sqrt(n);
    for(int i = 1;i <= n;++ i) b[i] = a[i] = read(),bel[i] = (i - 1) / k + 1;
    std::sort(b + 1,b + n +1);
    len = n;
    for(int i = 1;i <= n;++ i) a[i] = std::lower_bound(b + 1,b + len + 1,a[i]) - b;
    for(int i = 1;i <= m;i += 1) {
        l1[i] = read(),r1[i] = read(),l2[i] = read(),r2[i] = read(),l3[i] = read(),r3[i] = read();
        sum[i] = r1[i] - l1[i] + 1 + r2[i] - l2[i] + 1 + r3[i] - l3[i] + 1;
    }
    for(int i = 1;i <= m;i += whattt) {
        len = 0;
        for(int j = i;j <= i + whattt - 1; ++ j) {
            if(j > m) break;
            q[++ len] = Que(l1[j],r1[j],j - i + 1);
            q[++ len] = Que(l2[j],r2[j],j - i + 1);
            q[++ len] = Que(l3[j],r3[j],j - i + 1);
        }
        solve();
        for(int j = i;j < i + whattt; ++ j) {
            if(j > m) break;
            printf("%d\n",sum[j] - 3 * c[j - i + 1]);
            //return 0;
        }
    }
    return 0;
} 

原文地址:https://www.cnblogs.com/sssy/p/9637165.html

时间: 2024-10-08 13:31:32

luogu P4688 [Ynoi2016]掉进兔子洞 bitset 莫队的相关文章

luogu P4688 [Ynoi2016]掉进兔子洞

luogu 我们要求的答案应该是三个区间长度\(-3*\)在三个区间中都出现过的数个数 先考虑数列中没有相同的数怎么做,那就是对三个区间求交,然后交集大小就是要求的那个个数.现在有相同的数,考虑给区间中的数安排位置,即区间中如果出现了多个相同的数\(x\),那么就把第一个\(x\)放在\(x\)这种数要放的第一个位置,把第二个\(x\)放在第二个对应位置,依次类推.具体的,我们用桶维护区间内所有数的出现次数,然后给每种数安排一个初始下标\(ps_x\),使得后面过程中放数不会重叠,如果数\(x\

BZOJ 4939 [Ynoi2016]掉进兔子洞(莫队+bitset)

[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=4939 [题目大意] 给出一个数列,每个询问给出三个区间,问除去三个区间共有的数字外, 还剩下几个数字,注意删去的是共有的数字个数,不是数字种类,统计时候也一样 [题解] 首先,答案为区间长度和减去区间并数字个数和的三倍. 所以题目转化为求区间并.很显然在开始对数据可以进行离散化. 考虑每个数字只出现一次的情况,我们可以用bitset来统计区间某个数字是否存在, 莫队处理查询每个区间,

p4688 [Ynoi2016]掉进兔子洞

传送门 分析 我们考虑先将所有数离散化 之后我们对于每个状态用一个bitset来记录 其中第i段表示颜色i的信息 对于每一段信息均是段首若干1,剩余若干0表示这种颜色有多少个 于是我们不难想到莫队 答案就是1的总个数-异或值的1的个数乘3 但是我们发现开1e5*1e5的bitset会炸 于是我们考虑把1e5个询问分组,一次只考虑25000个询问 这个样子就能过了 原文地址:https://www.cnblogs.com/yzxverygood/p/10527348.html

bzoj 4939: [Ynoi2016]掉进兔子洞

有 m 个询问,每次询问三个区间,把三个区间中同时出现的数一个一个删掉,问最后三个区间剩下的数的个数和,询问独立. 注意这里删掉指的是一个一个删,不是把等于这个值的数直接删完, 比如三个区间是 [1,2,2,3,3,3,3] ,  [1,2,2,3,3,3,3] 与  [1,1,2,3,3],就一起扔掉了 1 个 1,1 个 2,2 个 3. Input 第一行两个数表示 n , m. 第二行 n个数表示 a[i]. 之后 m 行,每行 6 个数 l1 , r1 , l2, r2 , l3 ,

bzoj4939: [Ynoi2016]掉进兔子洞

将权值排序,设权值x排序后在[l,r]出现,x在区间中出现k次,则用[l,l+k-1]为1,[l+k,r]为0来表示x的出现次数 用bitset表示可重集中每个元素的出现次数,用莫队处理出询问区间对应的bitset,通过取and后求1的个数得到答案 #include<cstdio> #include<algorithm> #include<cmath> #include<cstring> typedef unsigned int u32; typedef u

[bzoj 4939][Ynoi 2016]掉进兔子洞

传送门 Description 一个长为 n 的序列 a. 有 m 个询问,每次询问三个区间,把三个区间中同时出现的数一个一个删掉,问最后三个区间剩下的数的个数和,询问独立. 注意这里删掉指的是一个一个删,不是把等于这个值的数直接删完, 比如三个区间是 [1,2,2,3,3,3,3] , [1,2,2,3,3,3,3] 与 [1,1,2,3,3],就一起扔掉了 1 个 1,1 个 2,2 个 3. Solution 弱化版是luoguP3674,这里放上它的题解 戳我 要找相同的元素就是集合求交

bzoj 4810 由乃的玉米田 - bitset - 莫队算法

由乃在自己的农田边散步,她突然发现田里的一排玉米非常的不美.这排玉米一共有N株,它们的高度参差不齐. 由乃认为玉米田不美,所以她决定出个数据结构题 这个题是这样的: 给你一个序列a,长度为n,有m次操作,每次询问一个区间是否可以选出两个数它们的差为x,或者询问一个区间是 否可以选出两个数它们的和为x,或者询问一个区间是否可以选出两个数它们的乘积为x ,这三个操作分别为操作1 ,2,3选出的这两个数可以是同一个位置的数 Input 第一行两个数n,m 后面一行n个数表示ai 后面m行每行四个数op

luogu3674 小清新人渣的本愿 (bitset+莫队)

对于加减,用bitset维护当前每个数有没有 对于乘,暴力枚举约数 然后莫队 复杂度$O(m(\sqrt{n}+\frac{c}{64}))$ 1 #include<bits/stdc++.h> 2 #define pa pair<ll,ll> 3 #define CLR(a,x) memset(a,x,sizeof(a)) 4 #define MP make_pair 5 using namespace std; 6 typedef long long ll; 7 const i

【Luogu】P4462异或序列(莫队)

题目链接 观察什么时候x到y之间那一段可以被统计 xorsum[x-1]^xorsum[y]=k xorsum[x-1]=xorsum[y]^k||xorsum[y]=xorsum[x-1]^k 莫队维护. #include<cstdio> #include<cstring> #include<algorithm> #include<cctype> #include<cstdlib> #include<cmath> #define m