\(\mathcal{Description}\)

  Link.

  给定序列 \(\{a_n\}\),处理 \(m\) 次操作:

  1. 给定 \(l,r,x\),把 \([l,r]\) 内所有 \(>x\) 的数减去 \(x\);
  2. 给定 \(l,r,x\),查询 \([l,r]\) 内 \(x\) 的出现次数。

  \(n\le10^6\),\(m\le5\times10^5\),\(0\le a_i,x\le10^5\)。

\(\mathcal{Solution}\)

  巧妙的分块题。

  分块,设块长为 \(B\),对于每一块,利用值域 \(V\) 不大,直接使用桶的方式维护信息。把桶看做一条线段 \([v_l,v_r]\),每次修改相当于把线段的后端截下一段平移到前端,可用启发式合并 + 并查集确保复杂度。最终复杂度为 \(\mathcal O(qB+\frac{nV}{B}+\frac{qn}{B})\),大概取 \(B=1.5\times10^3\) 就好。注意卡空间,对每个块离线处理。

\(\mathcal{Code}\)

/*~Rainybunny~*/

#include <bits/stdc++.h>

#define rep( i, l, r ) for ( int i = l, rep##i = r; i <= rep##i; ++i )
#define per( i, r, l ) for ( int i = r, per##i = l; i >= per##i; --i ) inline char fgc() {
static char buf[1 << 17], *p = buf, *q = buf;
return p == q && ( q = buf + fread( p = buf, 1, 1 << 17, stdin ), p == q )
? EOF : *p++;
} inline int rint() {
int x = 0, s = fgc();
for ( ; s < '0' || '9' < s; s = fgc() );
for ( ; '0' <= s && s <= '9'; s = fgc() ) x = x * 10 + ( s ^ '0' );
return x;
} inline void wint( const int x ) {
if ( 9 < x ) wint( x / 10 );
putchar( x % 10 ^ '0' );
} inline int imin( const int u, const int v ) { return u < v ? u : v; }
inline int imax( const int u, const int v ) { return u < v ? v : u; } const int MAXN = 1e6, MAXM = 6e5, MAXV = 1e5, MAXS = 1500;
int n, m, a[MAXN + 5], ans[MAXM + 5];
struct Event { int op, l, r, x; } evt[MAXM + 5];
int fa[MAXN + 5], siz[MAXV + 5], rt[MAXV + 5], ref[MAXN + 5]; inline int find( const int x ) {
return x == fa[x] ? x : fa[x] = find( fa[x] );
} inline void unite( int x, int y ) {
assert( rt[x] );
if ( rt[y] ) fa[rt[x]] = rt[y];
else ref[rt[y] = rt[x]] = y;
siz[y] += siz[x], siz[x] = rt[x] = 0;
} inline void solve( const int bl, const int br ) {
int vl = 0, vr = 0; rep ( i, bl, br ) vr = a[i] < vr ? vr : a[i];
memset( rt, 0, sizeof rt ), memset( siz, 0, sizeof siz );
rep ( i, bl, br ) {
if ( rt[a[i]] ) fa[i] = rt[a[i]];
else rt[a[i]] = fa[i] = i, ref[i] = a[i];
++siz[a[i]];
} rep ( i, 1, m ) {
int x = evt[i].x, l = evt[i].l, r = evt[i].r;
if ( r < bl || l > br ) continue;
if ( evt[i].op == 1 ) { // modify.
if ( vr - vl <= x ) continue;
if ( l <= bl && br <= r ) { // whole block update.
if ( x << 1 > vr - vl ) { // right to left.
per ( j, vr, vl + x + 1 ) if ( rt[j] ) unite( j, j - x );
vr = vl + x;
} else { // left to right.
rep ( j, vl + 1, vl + x ) if ( rt[j] ) unite( j, j + x );
vl += x;
}
} else { // partly update. curA = find(orgA)-vl.
rep ( j, bl, br ) {
a[j] = ref[find( j )];
siz[a[j]] = rt[a[j]] = 0;
a[j] -= vl;
} vl = vr = 0;
rep ( j, bl, br ) {
l <= j && j <= r && a[j] > x && ( a[j] -= x );
vr = vr < a[j] ? a[j] : vr;
if ( rt[a[j]] ) fa[j] = rt[a[j]];
else rt[a[j]] = fa[j] = j, ref[j] = a[j];
++siz[a[j]];
}
}
} else if ( vl + x <= vr ) { // meaningful query.
if ( l <= bl && br <= r ) { // whole block query.
ans[i] += siz[x + vl];
} else { // partly query.
rep ( j, imax( l, bl ), imin( r, br ) ) {
ans[i] += ref[find( j )] - vl == x;
}
}
}
}
} int main() {
n = rint(), m = rint();
rep ( i, 1, n ) a[i] = rint();
rep ( i, 1, m ) {
evt[i].op = rint();
evt[i].l = rint(), evt[i].r = rint(), evt[i].x = rint();
} for ( int l = 1, r; l <= n; l = r + 1 ) {
r = l + MAXS - 1; if ( r > n ) r = n;
solve( l, r );
} rep ( i, 1, m ) if ( evt[i].op == 2 ) {
wint( ans[i] ), putchar( '\n' );
}
return 0;
}

Solution -「Ynoi 2018」「洛谷 P4117」五彩斑斓的世界的更多相关文章

  1. 洛谷P4117 [Ynoi2018]五彩斑斓的世界 [分块,并查集]

    洛谷 Codeforces 又是一道卡常题-- 思路 YNOI当然要分块啦. 分块之后怎么办? 零散块暴力,整块怎么办? 显然不能暴力改/查询所有的.考虑把相同值的用并查集连在一起,这样修改时就只需要 ...

  2. 「区间DP」「洛谷P1043」数字游戏

    「洛谷P1043」数字游戏 日后再写 代码 /*#!/bin/sh dir=$GEDIT_CURRENT_DOCUMENT_DIR name=$GEDIT_CURRENT_DOCUMENT_NAME ...

  3. Solution -「JSOI 2019」「洛谷 P5334」节日庆典

    \(\mathscr{Description}\)   Link.   给定字符串 \(S\),求 \(S\) 的每个前缀的最小表示法起始下标(若有多个,取最小的).   \(|S|\le3\time ...

  4. Solution -「洛谷 P4372」Out of Sorts P

    \(\mathcal{Description}\)   OurOJ & 洛谷 P4372(几乎一致)   设计一个排序算法,设现在对 \(\{a_n\}\) 中 \([l,r]\) 内的元素排 ...

  5. Solution -「POI 2010」「洛谷 P3511」MOS-Bridges

    \(\mathcal{Description}\)   Link.(洛谷上这翻译真的一言难尽呐.   给定一个 \(n\) 个点 \(m\) 条边的无向图,一条边 \((u,v,a,b)\) 表示从 ...

  6. Solution -「APIO 2016」「洛谷 P3643」划艇

    \(\mathcal{Description}\)   Link & 双倍经验.   给定 \(n\) 个区间 \([a_i,b_i)\)(注意原题是闭区间,这里只为方便后文描述),求 \(\ ...

  7. 「洛谷4197」「BZOJ3545」peak【线段树合并】

    题目链接 [洛谷] [BZOJ]没有权限号嘤嘤嘤.题号:3545 题解 窝不会克鲁斯卡尔重构树怎么办??? 可以离线乱搞. 我们将所有的操作全都存下来. 为了解决小于等于\(x\)的操作,那么我们按照 ...

  8. 「洛谷3338」「ZJOI2014」力【FFT】

    题目链接 [BZOJ] [洛谷] 题解 首先我们需要对这个式子进行化简,否则对着这么大一坨东西只能暴力... \[F_i=\sum_{j<i} \frac{q_iq_j}{(i-j)^2}-\s ...

  9. 「BZOJ2733」「洛谷3224」「HNOI2012」永无乡【线段树合并】

    题目链接 [洛谷] 题解 很明显是要用线段树合并的. 对于当前的每一个连通块都建立一个权值线段树. 权值线段树处理操作中的\(k\)大的问题. 如果需要合并,那么就线段树暴力合并,时间复杂度是\(nl ...

随机推荐

  1. VM搭建Hadoop环境静态IP未起作用

    原文 https://www.toutiao.com/i6481452558941438478/ 问题描述 1.环境工具 VMware_workstation_full_12.5.2 CentOS-7 ...

  2. mongodb基础整理篇————常规操作[二]

    前言 简单整理一下常规操作. 正文 虽然一般说写代码看的是思想,但是呢,如果不知道mongodb 有哪些常用的操作,那么你怎么能知道mongodb是否符合你的需求,比如说如果聚合功能都没有,你得自己写 ...

  3. 一文看懂B端产品和C端产品

    大纲 什么是B端产品 什么是C端产品 为什么会产生B端产品和C端产品 怎么判断一个产品是B端还是C端 B端产品和C端产品存在哪些差异 C端产品经理如何向B端产品经理转型 写在最后   什么是B, Bu ...

  4. vue.config.js报错cannot set property "preserveWhitespace" of undefined

    vue.config.js报错cannot set property "preserveWhitespace" of undefined 最近在项目中配置webpack,由于vue ...

  5. Java异常理解之Exception in thread “main“ java.lang.ArrayIndexOutOfBoundsException

    这个异常是Java中的数组越界问题 当你使用不合法的索引访问数组是会出现这种错误例如: class Solution { public static int climbStairs(int n) { ...

  6. 【记录一个问题】golang的xorm组件更新数据库未生效

    代码中使用了类似的方式来更新数据库: func (writer *dbWriter) updateVersion(ctx context.Context, IP string, version str ...

  7. C# 在PDF文档中应用多种不同字体

    在PDF文档中,可绘制不同字体样式.不同语言的文字,可通过使用Standard字体.TrueType字体.CJK字体或者自定义(私有)等字体类型.下面通过C#程序代码来展示如何实现使用以上类型的字体来 ...

  8. es6中的导入与导出

    参考:https://www.cnblogs.com/sherrycat/p/11152994.html

  9. Typora下载安装教程(全面)

    Typora下载与安装 一:下载 1.1百度搜索 https://www.typora.io/ 点击链接进入后映入眼帘的就是一款简洁的Typora网页,然后下滑进入主页. 1.2点击Download( ...

  10. 免密码提交gitlab

    在你的用户目录下新建一个文本文件.git-credentials echo 'https://henry:123456@ggithub.com' > /root/.git-credentials ...