首页 > 其他分享 >【BZOJ4241】【回滚莫队模板题】历史研究

【BZOJ4241】【回滚莫队模板题】历史研究

时间:2023-05-17 17:32:05浏览次数:52  
标签:回滚 read BZOJ4241 int ls 端点 hxt 莫队 define


Description

给定一个序列,每次询问区间[l,r] [ l , r ] 内,所有权值与其出现次数的乘积的最大值。


Solution

回滚莫队模板题。
将询问以左端点所在块为第一关键字,右端点为第二关键字排序。
直接莫队、用std::set维护是O(nn‾√logn) O ( n n log ⁡ n ) 的。
对于所有左端点所在块相同的询问,右端点都是递增的,我们从该块的右端点依次向每个询问的右端点扩展,处理每次询问时,将左端向左移动得到答案后还原即可。
通过回滚莫队,我们可以将很多O(nn‾√logn) O ( n n log ⁡ n ) 的莫队优化成O(nn‾√) O ( n n ) 。


Code

/************************************************
 * Au: Hany01
 * Date: Aug 25th, 2018
 * Prob: BZOJ4241 历史研究

 * Inst: Yali High School
************************************************/

#include<bits/stdc++.h>

using namespace std;

typedef long long LL;
typedef long double LD;
typedef pair<int, int> PII;
#define rep(i, j) for (register int i = 0, i##_end_ = (j); i < i##_end_; ++ i)
#define For(i, j, k) for (register int i = (j), i##_end_ = (k); i <= i##_end_; ++ i)
#define Fordown(i, j, k) for (register int i = (j), i##_end_ = (k); i >= i##_end_; -- i)
#define Set(a, b) memset(a, b, sizeof(a))
#define Cpy(a, b) memcpy(a, b, sizeof(a))
#define x first
#define y second
#define pb(a) push_back(a)
#define mp(a, b) make_pair(a, b)
#define SZ(a) ((int)(a).size())
#define INF (0x3f3f3f3f)
#define INF1 (2139062143)
#define debug(...) fprintf(stderr, __VA_ARGS__)
#define y1 wozenmezhemecaia

template <typename T> inline bool chkmax(T &a, T b) { return a < b ? a = b, 1 : 0; }
template <typename T> inline bool chkmin(T &a, T b) { return b < a ? a = b, 1 : 0; }

inline int read() {
    static int _, __; static char c_;
    for (_ = 0, __ = 1, c_ = getchar(); c_ < '0' || c_ > '9'; c_ = getchar()) if (c_ == '-') __ = -1;
    for ( ; c_ >= '0' && c_ <= '9'; c_ = getchar()) _ = (_ << 1) + (_ << 3) + (c_ ^ 48);
    return _ * __;
}

const int maxn = 1e5 + 5;

int n, q, a[maxn], ls[maxn], bk, num, bel[maxn], cur, tot;
LL  ans[maxn];

struct Query { int id, l, r; } Q[maxn];
inline bool operator < (Query A, Query B) { return bel[A.l] == bel[B.l] ? A.r < B.r : A.l < B.l; }

inline void bfcalc(int t) {
    static int cnt[maxn];
    For(i, Q[t].l, Q[t].r)
        ++ cnt[a[i]], chkmax(ans[Q[t].id], (LL)cnt[a[i]] * ls[a[i]]);
    For(i, Q[t].l, Q[t].r) -- cnt[a[i]];
}

inline void Solve(int lb) {
    register int now = min(n, lb * bk), hxt = now + 1, hxt_ = hxt, cnt[maxn];
    register LL  Max_, Max;
    Set(cnt, 0), Max = 0;
    for (; cur <= n && bel[Q[cur].l] == lb; ++ cur) {
        if (bel[Q[cur].l] == bel[Q[cur].r]) { bfcalc(cur); continue; }
        while (now < Q[cur].r) ++ cnt[a[++ now]], chkmax(Max, (LL)cnt[a[now]] * ls[a[now]]);
        for (Max_ = Max; hxt > Q[cur].l; ++ cnt[a[-- hxt]], chkmax(Max_, (LL)cnt[a[hxt]] * ls[a[hxt]]));
        ans[Q[cur].id] = Max_;
        while (hxt < hxt_) -- cnt[a[hxt ++]];
    }
}

int main()
{
#ifdef hany01
    freopen("bzoj4241.in", "r", stdin);
    freopen("bzoj4241.out", "w", stdout);
#endif

    n = read(), q = read();
    For(i, 1, n) a[i] = ls[i] = read();
    sort(ls + 1, ls + 1 + n), tot = unique(ls + 1, ls + 1 + n) - ls - 1;
    For(i, 1, n) a[i] = lower_bound(ls + 1, ls + 1 + tot, a[i]) - ls;
    For(i, 1, q) Q[i].id = i, Q[i].l = read(), Q[i].r = read();
    bk = sqrt(n);
    For(i, 1, n) bel[i] = (i - 1) / bk + 1;
    num = bel[n], sort(Q + 1, Q + 1 + q), cur = 1;

    For(i, 1, num) Solve(i);
    For(i, 1, q) printf("%lld\n", ans[i]);

    return 0;
}

标签:回滚,read,BZOJ4241,int,ls,端点,hxt,莫队,define
From: https://blog.51cto.com/u_16117582/6292700

相关文章

  • git回滚代码
    1、未提交未提交有以下两种情况:1)已经在工作区修改了文件,但还未执行gitadd提交到暂存区。2)已经执行了gitadd提交到暂存作,但还未执行gitcommit提交本地仓库。这时候回退:gitreset--hard这样等于清空了暂存区和工作区,本地仓库回退到了最新的提交状态。2、已提交未推送......
  • errorCode: SYSTEM_EXCEPTION(UnexpectedRollbackException), message: 系统出现异常,请联系
    该异常为A方法加上@Transactional注解后,在方法内某段代码加上trycatch捕获且调用外部A方法也加上了异常捕获;原因是事务回滚是一旦它在方法内发现了exception,就会向上回滚,此时你将异常包裹,先行处理掉异常后事务自然回滚不了。解决方法是,直接try去掉,然后解决异常即可。......
  • 莫队学习笔记
    概念莫队是一种幽雅的暴力。用于处理区间问题。核心思想就是把询问离线下来,然后维护双指针按一定顺序处理每个询问。精髓就在于一定顺序。首先确定一个块长,然后将左端点的位置除以块长,把询问分成若干块。在每个块里按右端点排序。发现当块长为\(\sqrtn\)时两个指针各移动\(......
  • 数据结构-莫队二次离线
    莫队二次离线问题:给一个序列a,每次询问区间里面有几个逆序对刚刚又睡了半小时,终于睡醒了\(n,m\leq1e5\)实现询问首先想一想莫队:对于初始询问区间[l,r],将右指针r扩展到r+1,对于答案的贡献就是[l,r]里面大于a[r+1]的数量,写成数学公式就是\(\sum_{i=l}^r(a[i]>a[r+1])\)然后可......
  • 分块思想基础莫队
    分块将数组分成sqrt(n)块,每次进行区间操作或者查询的时候,对于完整的块可以通过预处理的信息o1得到,不完整的块直接暴力跑,所以最坏复杂度是sqrt(n)。分块模板constintN=100010,B=sqrt(N);intblock;intst[B],ed[B],bel[N];intsum[B],tag[B];inta[N],sz[B];vo......
  • 莫队
    一种用来处理序列上区间询问问题的算法。来看一下最经典的莫队题。区间不同数给定长为\(n\)的序列\(a\),有\(m\)组询问。每组询问给定一个区间\([l,r]\),求区间内有多少种不同的数。\(n,m\le10^5\),\(a_i\in[0,10^6]\)我们可以观察到如果我们已知\([l,r]\)的......
  • 分块+莫队算法
    分块复杂度\(O(n\sqrtn)\)主要目的是解决一些区间操作问题把区间拆分成\(\sqrt{n}\)大小的块每次碰到修改的操作,对于散块,直接暴力操作,对于整块,那么用一个\(tag\)进行标记即可也就是说对于一个操作\([l,r]\)来说我们需要进行操作主要分三步:暴力操作头散块,即\([l,......
  • oracle 数据库事务,提交,回滚,保存点,表的锁定,隐式锁,显示锁,写锁,读锁,排他锁,共享
    [color=red]数据库事务的概念[/color]事务是由相关操作构成的一个完整的操作单元。两次连续成功的COMMIT或ROLLBACK之间的操作,称为一个事务。在一个事务内,数据的修改一起提交或撤销,如果发生故障或系统错误,整个事务也会自动撤销。比如,我们去银行转账,操作......
  • kubectl 命令 --save-config 将部署信息添加到注解,防止deploy或webhook通过注释添加
    1、--save-config为什么需要使用kubctlapply保存配置?kubectl apply<file.yaml>--save-config创建或更新部署,并将部署另存为元数据。文件上说--save-config[=false]:如果为true,则当前对象的配置将保存在其注释中。当您将来要对此对象执行kubectlapply时,这非常有用。为什么......
  • git:回滚commit但未push代码
    这个场景经常出现,发现合并分支(从A分支合并到B分支)后,该分支(B分支)没有push提交权限,所以只能回滚(回滚B分支)合并merge后的记录,保持B分支干净,回到从前。gitlog查看提交日志命令:gitlog输入q则退出输出结果如下所示:解析:commit后是每次提交的唯一标志,从上往下时间是从近到远......