\(\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. nginx代理图片上传以及访问 nginx 图片上传完整版

    nginx代理图片上传 首先需要利用nginx代理图片访问参考 https://www.cnblogs.com/TJ21/p/12609017.html 编写接受文件的controller 1 @Po ...

  2. 为什么JavaWeb要分层

    首先bai让我们坐着时光机回到n年前的web开发.那个时候最早du都是静态的html页面,zhi后来有了数据库,有了所谓dao的动态页面,然后程序猿在编码的时候,会把所有的代码都写在页面上,包括数据库 ...

  3. manjaro20安装teamviewer出现sudo teamviewer –daemon start无响应

    问题 https://www.randomhacks.co.uk/the-teamviewer-daemon-is-not-running-please-start-the-daemon-ubuntu ...

  4. 利用词向量进行推理(Reasoning with word vectors)

    The amazing power of word vectors | the morning paper (acolyer.org) What is a word vector? At one le ...

  5. gorm概述与快速入门

    特性 全功能 ORM 关联 (Has One,Has Many,Belongs To,Many To Many,多态,单表继承) Create,Save,Update,Delete,Find 中钩子方 ...

  6. golang中结构体和结构体指针的内存管理

    p1是结构体,p2是结构体指针. 2. 声明并赋值结构体和结构体指针 package main import "fmt" type Person struct { name str ...

  7. JS、jQuery 刷新 iframe 的方法

    1.JavaScript 刷新 iframe 可以使用以下方法: document.getElementById('some_frame_id').contentWindow.location.rel ...

  8. Intellig Idea 常用快捷键列表

    修改方法如下: 点击 文件菜单(File) –> 点击 设置(Settings- Ctrl+Alt+S), –> 打开设置对话框. 在左侧的导航框中点击 KeyMap. 接着在右边的树型框 ...

  9. MapperScan注解 放在启动器上?

    package com.aaa.zxf; import org.mybatis.spring.annotation.MapperScan; import org.springframework.boo ...

  10. 基于redis实现tomcat的session会话保持 (转)

    出处:https://cloud.tencent.com/developer/article/1402997 基于redis实现tomcat的session会话保持 在实际生产中,我们经常部署应用服务 ...