首页 > 其他分享 >区间众数(分块)

区间众数(分块)

时间:2024-08-24 12:52:51浏览次数:11  
标签:typedef return 分块 int leq vx 众数 区间 inline

题目描述
给定一个序列\(a_1,a_2,\dots,a_n\),\(m\)个询问。

每个询问指定一个区间\([l,r]\),你需要输出\(a_l,a_{l+1},\dots,a_r\)这些数字里出现次数最多的数的出现次数。
输入
第一行一个整数\(T(1\leq T\leq 6)\),表示测试数据的组数。

每组数据第一行两个数\(n,m(1\leq n,m\leq 60000)\),表示序列长度与询问次数。

第二行\(n\)个整数\(a_1,a_2,\dots,a_n(0\leq a_i\leq 10^9)\)。

之后\(m\)行每行两个数\(l,r\),表示询问的区间。

本题强制在线,所以每次询问的\(l\)和\(r\)都要异或上一个询问的输出,你可以认为每组数据的第0个询问的答案是0。
输出
每组数据\(m\)行,每行一个数表示答案。
样例输入 Copy
1
3 3
3 3 3
3 3
3 3
3 3
样例输出 Copy
1
1
1

一定要注意分块的条件L+1>=R表示在同一块或者在相邻块,因为这个符号写反了调了一早上

#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;
#define x first
#define y second
typedef pair<int,int> PII;
typedef long long ll;
typedef unsigned long long ull;
typedef unsigned int uint;
typedef vector<string> VS;
typedef vector<int> VI;
typedef vector<vector<int>> VVI;
inline int log_2(int x) {return 31-__builtin_clz(x);}
inline int popcount(int x) {return __builtin_popcount(x);}
inline int lowbit(int x) {return x&-x;}
inline void up(int &a,int b) {if(a<b) a = b;}
vector<int> vx;
void divide(){sort(vx.begin(),vx.end());vx.erase(unique(vx.begin(),vx.end()),vx.end());}
inline int mp(int x) {return upper_bound(vx.begin(),vx.end(),x)-vx.begin();}
const int N = 60010 , B = 300;
//f[i][j]表示i块到j块的众数
int a[N],f[B][B],s[B][N],st[B],en[B],c[N];
int n,q;
inline int sum(int L,int R,int x) {return s[R][x] - s[L-1][x];}
void pre_f()
{
	int m = n/B;
    for(int i=0;i<=m;++i)
    {
        int ans = 0;
        for(int j=i;j<=m;++j)
        {
        	for(int k=st[j];k<=en[j];++k)
         	c[a[k]]++, up(ans,c[a[k]]);
         	f[i][j] = ans;
        } 
        memset(c,0,sizeof c);
    }
}
void pre_s()
{
	memset(s,0,sizeof s);
	int m = n/B;
	for(int i=1;i<=n;++i) s[i/B][a[i]] ++;
	for(int i=1;i<=m;++i)
	 for(int j=1;j<=n;++j)
	 s[i][j] += s[i-1][j];
}
int query(int l,int r)
{
    int L = l/B, R = r/B;
    //一定要注意此处是L+1>=R,符号不要写反了
    if(L+1>=R)
    {
        int ans = 0;
        for(int i=l;i<=r;++i) c[a[i]]++, up(ans,c[a[i]]);
        for(int i=l;i<=r;++i) c[a[i]] = 0;
        return ans;
    }
    int ans = f[L+1][R-1];
    for(int i=l;i<=en[L];++i) c[a[i]]++, up(ans,c[a[i]]+sum(L+1,R-1,a[i]));
    for(int i=st[R];i<=r;++i) c[a[i]]++, up(ans,c[a[i]]+sum(L+1,R-1,a[i]));
    for(int i=l;i<=en[L];++i) c[a[i]] = 0;
    for(int i=st[R];i<=r;++i) c[a[i]] = 0;
    return ans;
}
void solve()
{
    vx.clear();
    memset(s,0,sizeof s);
    cin>>n>>q;
    for(int i=1;i<=n;++i) en[i/B] = i;
    for(int i=n; i;--i) st[i/B] = i;
    for(int i=1;i<=n;++i) 
    {
        cin>>a[i];
        vx.push_back(a[i]);
    }
    //离散化
    divide();
    for(int i=1;i<=n;++i) a[i] = mp(a[i]);
    
    pre_f(), pre_s();
    memset(c,0,sizeof c);
    int ans = 0;
    while(q--)
    {
        int l,r;
        cin>>l>>r;
        ans = query(l^ans,r^ans);
        cout<<ans<<'\n';
    } 
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    int T;
    cin>>T;
    while(T--)
    {
        solve();
    }
}
 

标签:typedef,return,分块,int,leq,vx,众数,区间,inline
From: https://www.cnblogs.com/ruoye123456/p/18377654

相关文章

  • 分块、莫队、块状链表及一些根号方法 总结
    第二分块没改出来给我干破防了。提交记录:五彩斑斓的世界()。分块的种类序列分块:本质是在下标轴(\(i\))上分块。值域分块:本质是在值的轴(\(a_i\))上分块。操作分块:本质是在时间轴(一般是输入顺序)上分块。这几种分块应该是可以套的。分块、莫队、根号分治的核心平衡。平衡整块......
  • 线段树维护单调栈——区间查询版本 & 维护递减序列
    这次算是完全搞懂了吧()()(#include<bits/stdc++.h>#defineraedread#definecaclcalc#definepbpush_back#definepiipair<int,int>#defineintlonglong#definefifirst#definesesecond#definelsp<<1#definersp<<1|1usingn......
  • 维护区间信息
    维护区间信息(在线)暴力做法,\(O(n)\)修改,\(O(n)\)查询。但我们会发现多次询问会重复查询一些点,所以我们可以记录下一些区间的信息,查询时就可以节约时间。但我们记录的区间必须满足一些优秀性质:灵活性:记录下的区间组合灵活性高,即查询区间可以尽可能被记录下来的区间记录下来。......
  • 序列划分(区间DP)
    题目描述\(n\)个人,每个人手上有一个数\(a_i\)。将这些人分成若干组,组没有编号,要求每组人手上的数字之和都是质数。求合法的分组方案数。输入第一行一个正整数\(T(1\leqT\leq5)\),表示测试数据的组数。每组数据第一行一个正整数\(n(1\leqn\leq15)\)。每组数据第二行\(n\)......
  • NOI2022 众数
    经典题目,对于绝对众数只需要考虑这一个序列的中位数在序列中出现次数是否大于一半即可。这道题用线段树合并维护一下就做完了。点击查看代码#include<bits/stdc++.h>#definefirfirst#definesecsecond#defineintlonglong#definemkp(a,b)make_pair(a,b)usingname......
  • 代码随想录 -- 数组 -- 区间和
    58.区间和(第九期模拟笔试)(kamacoder.com)暴力解法大概率超时,应采用前缀和解法p[i] 表示vec[0]到vec[i]的累加和求vec[m] 到vec[n] 的和只需要 p[n]-p[m] 即可知识点input函数Python3 中raw_input()和input()进行了整合,去除了raw_input(),仅保留了i......
  • 题解:P10724 [GESP202406 七级] 区间乘积
    思路当一个数是完全平方数的时候,它的所有质因子的次数都是偶数。记\(x\)的质因子为\(p_1^{q1}\timesp_2^{q2}\timesp_3^{q3}...\timesp_v^{qv}\)。这些数可以通过次数的奇偶性用一个\(v\)位的二进制串\(B\)表示,\(B_i\)为\(0\)说明\(q_i\)为偶数,\(B_i\)为\(......
  • Stable Diffusion绘画 | ControlNet应用-Tile(分块)—tile_resample(分块-重采样)
    前言PS:StableDiffusion安装与在线平台推荐,请在公众号内的消息对话框中,发送关键词**「xiaoyaoSD」**要想使用SD生成高品质图片,放大增加分辨率是必不可少的环节。tile_resample(分块-重采样)主要是将图片切分成很多个分块,并识别每个分块的信息,最终通过特定算法把分......
  • 5章1节:用R语言进行定量数据的统计描述,文末有众数的自定义函数
    在科研中,很多资料经过整理之后,常常需要进行一系列的统计分析,以说明资料的特征。这种分析方法中,统计描述是最基础且最重要的部分之一。统计描述主要通过统计指标和统计图表来描述数据的分布规律及其数量特征,从而为后续的统计推断提供基础。统计描述不仅在医学科研中应用广泛,在......
  • 分块&莫队
    分块这是一种思想,不是一种数据结构。学校题单里的题大都是用这种思想做的。分块就是将一个序列分成多个不相交的区间,称为块。理想块长是\(\sqrt{n}\),至于为什么,它是由时间复杂度\(O(s+\frac{n}{s})(s\)为块长\()\)通过均值不等式算出来的。。。定义\(pos[i]\):表示\(i\)......