首页 > 其他分享 >数列分块:从入门到跑路——数列分块入门九题

数列分块:从入门到跑路——数列分块入门九题

时间:2023-01-10 10:37:29浏览次数:32  
标签:入门 分块 int 整块 sqrt mx maxn col 数列

第一题

区间加,单点询问

首先讲讲数列分块是个啥。

我们把数列分成一个个块,每个数属于块中的一部分。

对于整块,我们有复杂度优秀的操作(一般是 \(O(1)\) ),对于散块,我们暴力操作。

如果块长为 \(\sqrt n\),那么复杂度就是区间中散块长度+整块个数,复杂度为 \(O(n\sqrt n)\)。

然后回到这道题。对于整块,每次加时我们都往整块标记上加,散块我们直接往权值上加,询问时再把权值加上标记。总复杂度和上面推导一致,为 \(O(n\sqrt n)\)。

第二题

区间加,询问小于 \(x\) 的元素个数

如果序列有序,我们可以二分解决。因此我们尝试让每个块有序。

对于整块加,加完后还是有序的,可以打标记,最后再加就好。

对于散块,加完后不一定有序了,需要对散块重新排序。

看起来十分暴力,但是每次我们只会对散块排序,每次最大对 \(O(2\sqrt n)\) 排序,所以最大就是 \(O(n\sqrt n log(n \sqrt n))\)。可以通过此题。

第三题

区间加,询问前驱

第二题的 pro 版,改变一下二分得到的答案即可。

第四题

区间加,求区间和

第一题的 plus 版,要做的是额外记录整块权值和,把询问改成散块暴力+整块区间和就行。

第五题

区间开方,区间和

开方很少的次数后,数就会变成 \(1\),如果块内所有数都变成了 \(1\),这个块就不会再变了。

如果一整个块都变成了 \(1\),我们就可以 \(O(1)\) 修改与询问了。

如果还有数不是 \(1\),我们就整块打懒标记。最多只会有 31 个懒标记,如果记录最大值(用不着更改)还能更少。

第六题

单点插入,单点询问,数据随机

我们把每个块变成链表,方便插入,块之间也用链表相连,原因之后讲。

我们查找当前插入属于哪个块,插完后块大小 \(+1\)。如果块过大,对于块内询问不利。因此当块大过一个值时我们要把一个块裂成两个块。由于块之间由链表相连,所以实现简单。

第七题

区间加,区间乘,区间和

第四题的 plus 版,只需要额外考虑乘法对加法标记的影响。具体可参考 线段树2。

第八题

询问有多少数等于 \(c\),询问后将区间的所有数改为 \(c\)。

如果一整个块都是同一个数,那么只需要 \(O(1)\) 就可以进行询问与修改。

于是可以发现这是第五题的 plus 版。如果有散块修改要把整块的状态改成不相同。

第九题

区间众数

恭迎数列分块入门题真神。。。其实也没那么难。

离散化肯定是要的。

我们记录从第 \(i\) 个块到第 \(j\) 个块的众数,这个只需要 \(\sqrt n \sqrt n \sqrt n = n \sqrt n\) 的时间就可以得出。

然后我们再前缀和一下,记录从第 \(1\) 个块到第 \(i\) 个块的权值为 \(j\) 的点有多少个。

对于每个询问,我们把整块的众数求出来,对于散块中出现的每个数,加上它在整块中出现的次数,与现在的众数干一架。

散块中没出现的数,又不是众数的数呢?她不是整块的众数,又没有再次出现,肯定出现次数还是比原来整块的众数少的。就不用考虑了。

#include<bits/stdc++.h>
#define pii pair<int, int>
#define mp make_pair
#define ll long long
using namespace std;
const ll maxn = 4e4 + 5;
ll n, m;
ll a[maxn];
ll len;
ll col[maxn], si[maxn], val[maxn], lazy[maxn];
ll L[maxn], R[maxn];
ll zhong[505][505], b[maxn], p[505][maxn], ton[maxn];
pii w[maxn];
int pei[maxn];
bool cmp(pii a, pii b)
{
    return a.first < b.first;
}
int que(int l, int r)
{
    if(col[l] == col[r])
    {
        int mx = 0;
        for(int i = l;i <= r;i ++)
        {
            b[val[i]] ++;
            if(b[mx] < b[val[i]] || (b[val[i]] == b[mx] && val[i] < mx)) mx = val[i];
        }
        for(int i = l;i <= r;i ++) b[val[i]] = 0;
        return mx;
    }
    int mx = (col[r] - 1 >= col[l] + 1 ? zhong[col[l] + 1][col[r] - 1] : 0), mxd = 0;
    if(mx) mxd = p[col[r] - 1][mx] - p[col[l]][mx];
    vector<int> cun;
    for(int i = l;col[i] == col[l];i ++)
    {
        // cout << val[i] << ' ';
        if(val[i] == mx) 
        {
            mxd ++;
            continue;
        }
        b[val[i]] ++;
        if(b[val[i]] == 1) cun.push_back(val[i]);
    }
    for(int i = r;col[i] == col[r];i --)
    {
        if(val[i] == mx) 
        {
            mxd ++;
            continue;
        }
        b[val[i]] ++;
        if(b[val[i]] == 1) cun.push_back(val[i]);
    }
    for(auto i : cun)
    {
        int big = b[i] + (col[r] - 1 >= col[l] + 1 ? p[col[r] - 1][i] - p[col[l]][i] : 0);
        if(big > mxd || (big == mxd && i < mx)) mx = i, mxd = big;
    }
    int ans = mx;
    for(int i = l;col[i] == col[l];i ++) b[val[i]] = 0;
    for(int i = r;col[i] == col[r];i --) b[val[i]] = 0;
    return ans;
}
signed main()
{
	freopen("text.in", "r", stdin);
	freopen("text.out", "w", stdout);
	ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	cin >> n >> m;
	for(ll i = 1;i <= n;i ++) cin >> w[i].first, w[i].second = i;
    sort(w + 1, w + n + 1, cmp);
    int tot = 0, last = -1;
    for(int i = 1;i <= n;i ++) 
    {
        if(last != w[i].first) last = w[i].first, tot ++;
        pei[tot] = w[i].first;
        val[w[i].second] = tot;
    }
    len = sqrt(n);
    ll sp = 1, siz = 0;
    for(ll i = 1;i <= n;i ++)
    {
        if(siz == len)
        {
            R[sp] = i - 1, si[sp] = siz;
            siz = 0, sp ++, L[sp] = i;            
        }
        siz ++;
        col[i] = sp;
    }
    si[sp] = siz;
    L[1] = 1, R[sp] = n;
    last = 1;
    for(int i = 1;i <= n;i ++)
    {
        if(last != col[i])
        {
            i --;
            for(int j = 1;j <= n;j ++) p[col[i]][j] = b[j];
            last = col[i];
            i ++;
        }
        b[val[i]] ++;
    }
    for(int i = 1;i <= sp;i ++)
    {
        int mx = 0;
        for(int j = 1;j <= n;j ++) b[j] = 0;
        for(int j = L[i];j <= R[i];j ++) 
        {
            b[val[j]] ++;
            if(b[val[j]] > b[mx] || (b[val[j]] == b[mx] && val[j] < mx)) mx = val[j];
        }
        zhong[i][i] = mx;
        for(int j = i + 1;j <= sp;j ++)
        {
            for(int k = L[j];k <= R[j];k ++)
            {
                b[val[k]] ++;
                if(b[val[k]] > b[mx] || (b[val[k]] == b[mx] && val[k] < mx)) mx = val[k];
            }
            zhong[i][j] = mx;
        }
    }
    for(int i = 1;i <= n;i ++) b[i] = 0;
    int l, r, x = 0;
    for(int _ = 1;_ <= m;_ ++)
    {
        cin >> l >> r;
        l = ((l + x - 1) % n) + 1;
        r = ((r + x - 1) % n) + 1;
        if(l > r) swap(l, r);
        x = pei[que(l, r)];
        cout << x << endl;
    }
	return 0;
}

标签:入门,分块,int,整块,sqrt,mx,maxn,col,数列
From: https://www.cnblogs.com/closureshop/p/17039353.html

相关文章

  • Python笔记(5)——if 语句一:条件测试(Python编程:从入门到实践)
    每条if语句的核心都是一个值为True或False的表达式。Python根据条件测试的值为True还是False来决定是否执行if语句中的代码。如果条件测试的值为True,Python就执行紧跟......
  • EasyX入门笔记
    基于EasyX的C++图形化界面实现什么是EasyX?EasyX是针对C++的图形库,可以帮助C/C++初学者快速上手图形和游戏编程。比如,可以基于EasyX图形库很快的用几何图形画一......
  • Linux入门笔记
    Linux命令command[-options][parameter]options可选选项,控制命令的行为细节parameter可选参数,控制命令的指向目标ls命令ls[-a-l-h][Linux路径]在命令行中,以......
  • HTML 入门
    01.html的历史1982年,TimBerners-Lee建立HTML1993年6月,HTML由IETF工作小組发布草案1994年10月,W3C成立,网络应用发展的标准规范交由W3C协会制定及推广1995年11......
  • 入门2年的ctf新手自述--web方向
    为什么想写这篇博客,为什么要要跟大家分享?因为我的确入门费了非常多的时间,有很多坎。首先是自己的精力因为很多事情,确实分散了很多,有创新创业项目、学生工作、学业等等,没有......
  • 区块链入门 ③ - 交易
    区块链入门③-交易交易概述比特币交易本质上包含交易参与者价值转移的相关信息数据结构。比特币区块链是一本全球复式记账总账簿,每笔交易都是在比特币区块链上的一个......
  • Python笔记(3)——列表二:操作列表(Python编程:从入门到实践)
    一、遍历列表1. 遍历整个列表:使用for循环1colors=['red','yellow','blue','green']#定义列表2forcolorincolors:#使用循环:从列表中提取一个元素并将其存......
  • OpenHarmony开发07 —— 小熊派入门
    OpenHarmony开发07——小熊派入门BearPi-HMNano入门applications/BearPi/BearPi-HM_Nano/docs/quick-start/BearPi-HM_Nano十分钟上手.md·小熊派开源社区/BearPi-......
  • [VueJsDev] 快速入门 - vue项目根目录配置文件
    [VueJsDev]目录列表https://www.cnblogs.com/pengchenggang/p/17037320.htmlvue项目根目录配置文件:::details目录目录vue项目根目录配置文件Part.1:package.json......
  • [VueJsDev] 快速入门 - vscode 自动格式化
    [VueJsDev]目录列表https://www.cnblogs.com/pengchenggang/p/17037320.htmlvscode自动格式化(vue):::details目录目录vscode自动格式化(vue)Step.1:.editorcon......