\(\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. PowerShell 管道符之Select的使用方法【一】

    之前我文章中我们略微提到过管道符的操作,但并不多,这篇主要讲解一下详细的使用方法 假设我们要对数组中的数字1-10中我想要从右往左换句话说就是从字符串最后一个字开始倒过来往前数截取6个子字符串时可以这 ...

  2. Tomcat8/9的catalina.out中文乱码问题解决

    OS: Red Hat Enterprise Linux Server release 7.8 (Maipo) Tomcat: 9 中文显示为???问号 在$CATALINA_HOME/conf下的l ...

  3. js对cookie的操作:读、写、删

    js读写cookie //JS操作cookies方法!//写cookiesfunction setCookie(name,value){var Days = 30;var exp = new Date ...

  4. centos7 单用户模式修改root密码

    1. 在虚拟机重启客户机后.会出现下面进入界面.按e键 2.按了e键后,会出现下面的界面.此时按↓键.找到linux16 3.将光标移动到UTF-8后面,添加init=/bin/sh,并按 ctrl  ...

  5. 第10组 Alpha冲刺 (4/6)

    1.1基本情况 ·队名:今晚不睡觉 ·组长博客:https://www.cnblogs.com/cpandbb/p/13982696.html ·作业博客:https://edu.cnblogs.co ...

  6. JAVA之G1垃圾回收器

    概述 G1 GC,全称Garbage-First Garbage Collector,通过-XX:+UseG1GC参数来启用,作为体验版随着JDK 6u14版本面世,在JDK 7u4版本发行时被正式推 ...

  7. Bootstrap实战 - 注册和登录

    一.介绍 注册和登录在社交和商业网站中是必不可少的一个部分. 二.知识点 2.1 标签页 2.1.1 基础标签页 标签页的使用与导航栏类似,同时都依赖于基础样式 nav,不同的是附加样式变成了 nav ...

  8. linux与shell介绍 - 进程与线程

    linux linux与windows的区别 linux的文件结构 Linux基本命令 ls: 列出目录 cd: 切换目录 pwd: 显示当前目录 mkdir: 创建一个新的目录 rmdir: 删除一 ...

  9. 007 Linux 命令三剑客之-awk

    01 一起来认识 awk! Linux 命令三剑客,sed.grep.awk. sed:擅长数据修改. grep:擅长数据查找定位. awk:擅长数据切片,数据格式化,功能最复杂. awk 更适合格式 ...

  10. K8s PV and PVC and StorageClass

    PVC和PV之间没有依靠ID.名称或者label匹配,而是靠容量和访问模式,PVC的容量和访问模式需要是某个PV的子集才能自动匹配上.注意:PVC和PV是一对一的,也即一个PV被一个PVC自动匹配后, ...