【题目链接】 http://www.lydsy.com/JudgeOnline/problem.php?id=4939

【题目大意】

  给出一个数列,每个询问给出三个区间,问除去三个区间共有的数字外,
  还剩下几个数字,注意删去的是共有的数字个数,不是数字种类,统计时候也一样

【题解】

  首先,答案为区间长度和减去区间并数字个数和的三倍。
  所以题目转化为求区间并。很显然在开始对数据可以进行离散化。
  考虑每个数字只出现一次的情况,我们可以用bitset来统计区间某个数字是否存在,
  莫队处理查询每个区间,保存其bitset的值,最后求交即可,
  现在考虑每个数字出现多次的情况,
  我们发现经过离散的数据之间空位数量恰好可以用来标出现多次的数据,
  比如1 4 4 9 9,离散后为 1 2 2 4 4,
  我们可以将多出来的2标在3位置,4标在5位置,那么就可以用bitset统计了。
  - Me : 询问区间存不下怎么办?
  - Claris :将询问分批进行处理,单次处理25000个询问
  - Me : 超时了欸……
  - Claris : 这题卡常数,要手写bitset.
  - Me : 你的代码为什么有6.7k?
  - Claris :我分出现一次,两次和跟多次讨论
  - Me : 我……还是咸鱼吧……

【代码】

#include <cstdio>
#include <algorithm>
#include <bitset>
#include <cmath>
using namespace std;
typedef unsigned long long ULL;
const int N=100010,M=N<<2;
int limit,n,m,pos[N],a[N],cnt[N],Ans[N],mark[N];
struct Q{
int l,r,id;
friend bool operator < (const Q &a,const Q &b){
return pos[a.l]<pos[b.l]||(pos[a.l]==pos[b.l]&&a.r<b.r);
}
}ask[M];
int read(int &x){
int f=1;char ch=getchar();x=0;
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
x*=f;
}
int disc[N];
int remark(int x){
int l=1,r=n,res=0;
while(l<=r){
int mid=(l+r)>>1;
if(disc[mid]<x)l=mid+1;
else res=mid,r=mid-1;
}return res;
}
const int B=1567,K=25000;
ULL v[B],f[K+3][B];
int u[65537],tmp,U;
void flip(int x){v[x>>6]^=1ULL<<(x&63);}
void Copy(ULL*a){
int i=0;
for(;i+13<=U;i+=14){
for(int j=0;j<14;j++)a[i+j]=v[i+j];
}for(;i<=U;i++)a[i]=v[i];
}
void And(ULL*a){
int i=0;
for(;i+13<=U;i+=14){
for(int j=0;j<14;j++)a[i+j]&=v[i+j];
}for(;i<=U;i++)a[i]&=v[i];
}
void popcount(ULL x){tmp+=u[x&65535]+u[x>>16&65535]+u[x>>32&65535]+u[x>>48];}
int count(ULL*a){
int i=tmp=0;
for(;i+13<=U;i+=14){
for(int j=0;j<14;j++)popcount(a[i+j]);
}for(;i<=U;i++)popcount(a[i]);
return tmp;
}
void init(){for(int i=1;i<65536;i++)u[i]=u[i>>1]+(i&1);}
int main(){
read(n); read(m);
U=n>>6; init();
limit=(int)sqrt(n+0.5);
for(int i=1;i<=n;i++)read(a[i]),disc[i]=a[i],pos[i]=(i-1)/limit+1;
sort(disc+1,disc+n+1);
for(int i=1;i<=n;i++)a[i]=remark(a[i]);
//for(int i=1;i<=n;i++)printf("%d\n",a[i]);
int pos=0,l=1,r=0;
while(pos<m){
int tot=0;
for(int i=1;i<=25000&&i+pos<=m;i++){
tot+=3;
Ans[i]=0;
mark[i]=0;
read(ask[i*3-2].l); read(ask[i*3-2].r); ask[i*3-2].id=i;
read(ask[i*3-1].l); read(ask[i*3-1].r); ask[i*3-1].id=i;
read(ask[i*3].l); read(ask[i*3].r); ask[i*3].id=i;
Ans[i]+=ask[i*3-2].r-ask[i*3-2].l+1;
Ans[i]+=ask[i*3-1].r-ask[i*3-1].l+1;
Ans[i]+=ask[i*3].r-ask[i*3].l+1;
}sort(ask+1,ask+tot+1);
for(int i=1;i<=tot;i++){
for(;r<ask[i].r;r++){flip(a[r+1]+cnt[a[r+1]]);cnt[a[r+1]]++;}
for(;l>ask[i].l;l--){flip(a[l-1]+cnt[a[l-1]]);cnt[a[l-1]]++;}
for(;l<ask[i].l;l++){cnt[a[l]]--;flip(a[l]+cnt[a[l]]);}
for(;r>ask[i].r;r--){cnt[a[r]]--;flip(a[r]+cnt[a[r]]);}
if(mark[ask[i].id])And(f[ask[i].id]);
else Copy(f[ask[i].id]),mark[ask[i].id]=1;
}tot/=3;
for(int i=1;i<=tot;i++)printf("%d\n",Ans[i]-3*count(f[i]));
pos+=tot;
}return 0;
}

BZOJ 4939 [Ynoi2016]掉进兔子洞(莫队+bitset)的更多相关文章

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

    传送门 解题思路 刚开始想到了莫队+\(bitset\)去维护信息,结果发现空间不太够..试了各种奇技淫巧都\(MLE\),最后\(\%\)了发题解发现似乎可以分段做..这道题做法具体来说就是开\(3 ...

  2. BZOJ.4939.[Ynoi2016]掉进兔子洞(莫队 bitset 分组询问)

    BZOJ 洛谷 删掉的数即三个区间数的并,想到bitset:查多个区间的数,想到莫队. 考虑bitset的每一位如何对应每个数的不同出现次数.只要离散化后不去重,每次记录time就可以了. 但是如果对 ...

  3. [Luogu 4688] [Ynoi2016]掉进兔子洞 (莫队+bitset)

    [Luogu 4688] [Ynoi2016]掉进兔子洞 (莫队+bitset) 题面 一个长为 n 的序列 a.有 m 个询问,每次询问三个区间,把三个区间中同时出现的数一个一个删掉,问最后三个区间 ...

  4. BZOJ4939: [Ynoi2016]掉进兔子洞(莫队 bitset)

    题意 题目链接 一个长为 n 的序列 a. 有 m 个询问,每次询问三个区间,把三个区间中同时出现的数一个一个删掉,问最后三个区间剩下的数的个数和,询问独立. 注意这里删掉指的是一个一个删,不是把等于 ...

  5. 洛谷P4135 Ynoi2016 掉进兔子洞 (带权bitset?/bitset优化莫队 模板) 题解

    题面. 看到这道题,我第一反应就是莫队. 我甚至也猜出了把所有询问的三个区间压到一起处理然后分别计算对应询问答案. 但是,这么复杂的贡献用什么东西存?难道要开一个数组 query_appear_tim ...

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

    题目链接 luogu P4688 [Ynoi2016]掉进兔子洞 题解 莫队维护bitset区间交个数 代码 // luogu-judger-enable-o2 #include<cmath&g ...

  7. 【洛谷 P4688】 [Ynoi2016]掉进兔子洞(bitset,莫队)

    题目链接 第一道Ynoi 显然每次询问的答案为三个区间的长度和减去公共数字个数*3. 如果是公共数字种数的话就能用莫队+bitset存每个区间的状态,然后3个区间按位与就行了. 但现在是个数,bits ...

  8. bzoj千题计划320:bzoj4939: [Ynoi2016]掉进兔子洞(莫队 + bitset)

    https://www.lydsy.com/JudgeOnline/problem.php?id=4939 ans= r1-l1+1 + r2-l2+1 +r3-l3+1 - ∑ min(cnt1[i ...

  9. BZOJ4939 Ynoi2016掉进兔子洞(莫队+bitset)

    容易发现要求三个区间各数出现次数的最小值.考虑bitset,不去重离散化后and一发就可以了.于是莫队求出每个区间的bitset.注意空间开不下,做多次即可.输出的东西错了都能调一年服了我了. #in ...

随机推荐

  1. 将四个按钮放入一个父控件的好处:方便移动,只需要改变父控件的y值,就可移动四个按钮

      将四个按钮放入一个父控件的好处:方便移动,只需要改变父控件的y值, 就可移动四个按钮               https://www.evernote.com/shard/s227/sh/78 ...

  2. cocos2dx 某缩放的页面 CCTableView最后一个标签无法点中

    有一个二级界面,在ipad4下面放大到1.6倍,直接对最外层的CCLayer缩放的,里面包含有CCTableView.结果运行的时候无法选中到最后一个标签,无论总的标签是2个还是更多,单步调试,发现到 ...

  3. YII 框架查询

    基础查询 Customer::find()->one();    此方法返回一条数据: Customer::find()->all();    此方法返回所有数据: Customer::f ...

  4. 20151024_002_C#基础知识(ArrayList,Hashtable,List,Dictionary)

    1:ArrayList 和 Hashtable(哈希表) 1.1:ArrayList ArrayList list = new ArrayList(); list.Add(); list.AddRan ...

  5. Windows下基于python3使用word2vec训练中文维基百科语料(二)

    在上一篇对中文维基百科语料处理将其转换成.txt的文本文档的基础上,我们要将为文本转换成向量,首先都要对文本进行预处理 步骤四:由于得到的中文维基百科中有许多繁体字,所以我们现在就是将繁体字转换成简体 ...

  6. PKUWC 2019 自闭记

    PKUWC 2019 自闭记 Day -1 考前天天在隔壁的物竞教室划水(雀魂,能和吉老师一起玩的游戏都是好游戏),没有做题. Day 0 早上8:16的高铁,到广州南居然要6个小时...不知道福州和 ...

  7. Python3 hashlib模块和hmac 模块(加密)

    hashlib 是一个提供了一些流行的hash算法的 Python 标准库.其中所包括的算法有 md5, sha1, sha224, sha256, sha384, sha512等常用算法 MD5加密 ...

  8. epoll内核源码分析

    转载:https://www.nowcoder.com/discuss/26226?type=0&order=0&pos=27&page=1 /*  *  fs/eventpo ...

  9. skb管理函数之alloc_skb、dev_alloc_skb、kfree_skb、dev_kfree_skb、consume_skb

    alloc_skb--分配skb dev_alloc_skb--分配skb,通常被设备驱动用在中断上下文中,它是alloc_skb的封装函数,因为在中断处理函数中被调用,因此要求原子操作(GFP_AT ...

  10. 安全测试===sqlmap(贰)转载

    十二.列举数据 这些参数用于列举出数据库管理系统信息.数据结构和数据内容. 1.一键列举全部数据 参数:--all 使用这一个参数就能列举所有可访问的数据.但不推荐使用,因为这会发送大量请求,把有用和 ...