首页 > 其他分享 >P4688 Ynoi2016 掉进兔子洞

P4688 Ynoi2016 掉进兔子洞

时间:2024-07-07 21:42:36浏览次数:19  
标签:int 元素 个数 兔子 Ynoi2016 bitset it1 it2 P4688

P4688 Ynoi2016 掉进兔子洞

经典莫队加 bitset

思路

不难发现最终答案就是:

\[(r_1-l_1+1)+(r_2-l_2+1)+(r_3-l_3+1)-3\times size \]

其中 \(size\) 表示 3 个区间内出现了多少个公共元素。

看到这么多区间,不妨有把区间拆下来搞莫队的想法。

先不考虑询问个数的限制,我们考虑使用 bitset 维护出现多少个公共元素。

然而 bitset 维护出来的是多少种而不是个数。

又然而我们可以先将序列离散化,离散化时每个元素的新值赋为小于等于它的元素的个数。

在莫队加入一个节点时,把 bitset 中的第 \(p-cnt_p\) 位标为 \(1\)。

\(cnt_p\) 为当前区间内 \(p\) 元素的个数。

然后你就会发现,bitset 中不同的值的元素所储存位置是不同的(这个显而易见)。

然后你又发现,bitset 中不同区域的 \(1\) 的个数代表了某些值相等的元素的个数。

接着你把 3 个区间分别的 bitset 求交,统计 \(1\) 的个数,就求出了 \(size\)。

然而一次性不可以处理这么多的区间,我们把询问分组处理即可。

时间复杂度 \(\frac{n^2\sqrt n}{w}\),然而卡不到莫队上限。

CODE

#include<bits/stdc++.h>
using namespace std;

#define M 2e4

const int maxn=1e5+5,maxm=2e4+5;

struct qry
{
    int l,r,t;
}q[maxm*3];

int n,m,tot=1;
int a[maxn],cnt[maxn],nans[maxm];

bitset<maxn>ans[maxm],nb;

map<int,int>mp;

inline bool cmp1(qry a,qry b){return a.l<b.l;}
inline bool cmp2(qry a,qry b){return a.r<b.r;}
inline void ins(int a){nb[a-cnt[a]]=1;cnt[a]++;}
inline void del(int a){cnt[a]--;nb[a-cnt[a]]=0;}
inline void solve()
{
    if(tot>=m) return ;
    int tp=0;
    for(int i=1;i<=M&&tot<=m;i++,tot++)
    {
        ++tp;scanf("%d%d",&q[tp].l,&q[tp].r);q[tp].t=i;nans[i]+=q[tp].r-q[tp].l+1;
        ++tp;scanf("%d%d",&q[tp].l,&q[tp].r);q[tp].t=i;nans[i]+=q[tp].r-q[tp].l+1;
        ++tp;scanf("%d%d",&q[tp].l,&q[tp].r);q[tp].t=i;nans[i]+=q[tp].r-q[tp].l+1;
    }
    for(int i=1;i<=tp/3;i++) ans[i].set();
    sort(q+1,q+tp+1,cmp1);
    for(int i=1;i<=tp;i+=320)
    {
        int r=min(i+319,tp);
        sort(q+i,q+r+1,cmp2);
    }
    int nl=0,nr=0;
    for(int i=1;i<=tp;i++)
    {
        if(nr<q[i].l)
        {
            for(int j=nl;j<=nr;j++) del(a[j]);
            nl=q[i].l,nr=q[i].r;
            for(int j=nl;j<=nr;j++) ins(a[j]);
        }
        else
        {
            while(nl<q[i].l) del(a[nl]),nl++;
            while(nl>q[i].l) nl--,ins(a[nl]);
            while(nr<q[i].r) nr++,ins(a[nr]);
            while(nr>q[i].r) del(a[nr]),nr--;
        }
        ans[q[i].t]&=nb;
    }
    for(int i=nl;i<=nr;i++) del(a[i]);
    for(int i=1;i<=tp/3;i++) printf("%lld\n",nans[i]-ans[i].count()*3);
    for(int i=1;i<=tp/3;i++) nans[i]=0;tp=0;
}

int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++) scanf("%d",&a[i]),mp[a[i]]++;
    map<int,int>::iterator it2,it1;
    for(it1=mp.begin(),it2=it1,it2++;it2!=mp.end();it1++,it2++) it2->second+=it1->second;
    for(int i=1;i<=n;i++) a[i]=mp[a[i]];
    for(int i=1;i<=5;i++) solve();
}

标签:int,元素,个数,兔子,Ynoi2016,bitset,it1,it2,P4688
From: https://www.cnblogs.com/binbinbjl/p/18288961

相关文章

  • 【递推】兔子繁殖问题
    题目描述如果有一对小兔,每一个月都生下一对小兔,而所生下的每一对小兔在出生后的第三个月也都生下一对小兔。那么,由一对兔子开始,n个月后有多少对小兔子呢?输入输入一个数字n(1≤n≤100),代表题目中询问的月份。输出对于每个询问,输出一行整数,代表n月的时候,小兔子的数量。......
  • 「杂题乱刷」洛谷 P10468 兔子与兔子
    题目链接P10468兔子与兔子解题思路字符串哈希板子题。思路就是我们给字符串的每一个前缀和后缀都用一种特定的方式使其变为一个值,比如取一个乘数和模数,可以证明这样出错的概率极低。参考代码这里使用自然溢出三哈希。#include<bits/stdc++.h>usingnamespacestd;#defin......
  • C117 莫队配合 bitset P4688 [Ynoi2016] 掉进兔子洞
    视频链接:C117莫队配合bitsetP4688[Ynoi2016]掉进兔子洞_哔哩哔哩_bilibili   LuoguP4688[Ynoi2016]掉进兔子洞//莫队配合bitsetO(n*sqrt(n))#include<iostream>#include<cstring>#include<algorithm>#include<cmath>#include<bitset>usin......
  • 1238 - 【入门】统计每个月兔子的总数
    题目描述有一对兔子,从出生后第3个月起每个月都生一对兔子,一对小兔子长到第三个月后每个月又生一对兔子,假如兔子都不死,问第n个月(n<=50)的兔子总数为多少对?输入:输入1个整数n,表示第几个月输出:第n个月兔子的总数量有多少对?样例:输入9输出34#include<bits/stdc++.h>usi......
  • P4690 [Ynoi2016] 镜中的昆虫
    P4690[Ynoi2016]镜中的昆虫本质就是区间修改,区间数颜色弱化一下,先考虑不带修的情况,也就是P1972[SDOI2009]HH的项链其难点在于区间颜色的去重,需要想一个办法让区间内一个颜色只被数一次我们可以去维护一个\(Nxt\)数组,表示下一个与当前位置颜色相同的位置若当前位......
  • 习题4-11 兔子繁衍问题
    探索--题目集索引一对兔子,从出生后第3个月起每个月都生一对兔子。小兔子长到第3个月后每个月又生一对兔子。假如兔子都不死,请问第1个月出生的一对兔子,至少需要繁衍到第几个月时兔子总数才可以达到N对?输入格式:输入在一行中给出一个不超过10000的正整数N。输出格式:在一行......
  • (斐波那契数列),假如兔子都不死,问到第12个月时一共有多少只兔子 //(有一对兔子,从出生后第
    //斐波那契数列,计算兔子的数量:11235813......从第三个数开始,//后一个数都是前两个数的和,假如兔子都不死,问到第12个月时一共有多少只兔子//(有一对兔子,从出生后第三个月开始,每一个月生一对兔子,小兔子同理)publicclassRabitDemo1{//斐波那契数列,计算兔子的数量:1......
  • C语言之兔子生产问题
    /#include<stdio.h>main(){longfib1=1,fib2=1,fib;//定义长整型变量,fib1表示当前前一个月的兔子数,fib2表示当前前两个月的兔子数,fib表示当前月份兔子数inti;//月份变量printf("%12ld%12ld",fib1,fib2);//输出第一个月和第二个月的兔子数,%ld用于输出长整型数据,而%12l......
  • 力扣781.森林中的兔子
    题目:森林中有未知数量的兔子。提问其中若干只兔子"还有多少只兔子与你(指被提问的兔子)颜色相同?",将答案收集到一个整数数组answers中,其中answers[i]是第i只兔子的回答。给你数组answers,返回森林中兔子的最少数量。实现方法:由于要求兔子最少数量,可以假定答案相同的......
  • P4690 [Ynoi2016] 镜中的昆虫 题解
    题目链接:镜中的昆虫经典题了,我们首先回顾下颜色数的常见做法统计:对每个位置维护一个\(pre_i\),表示与当前位置相同的颜色上一次出现位置。那么我们分讨一下。查询\([l,r]\)得到颜色数,对于\(pre_i<l\)的\(i\)点,显然它就是这个区间内\(a_i\)对应颜色出现的第一个位置,我们......