\(\mathcal{Description}\)

  Link.

  给定序列 \(\{a_n\}\) 和 \(q\) 次操作,操作内容如下:

  1. 给出 \(l,r,k,b\),声明一个修改方案,表示 \(\forall i\in[l,r],~a_i\leftarrow (ka_i+b)\bmod m\)。
  2. 给出 \(l,r,x\),求将第 \(l\) 到第 \(r\) 个修改方案作用于序列时,\(a_x\) 的值。

  强制在线,\(n\le10^5\),\(q\le6\times10^5\)。

\(\mathcal{Solution}\)

  一种类似在线建线段树的 trick。

  若允许离线,自然可以建立关于修改方案的线段树,每个结点维护对应区间内的修改依次作用后,每个 \(a\) 值会变成的 \(ka+b\)。不同的 \((k,b)\) 形成的区间个数是与结点对应区间长度同阶的,所以一共有 \(\mathcal O(n\log n)\) 个区间。查询时,在每个区间内二分找到会影响 \(x\) 位置的 \((k,b)\),更新答案,单次复杂度是 \(\mathcal O(\log^2n)\) 的。

  转为在线,注意到当线段树结点对应区间内的修改操作全部声明时,这个结点的信息才有效,所以当且仅当区间内修改操作全部声明时,在结点处归并左右儿子信息,均摊复杂度就是离线建树的复杂度。最终复杂度为 \(\mathcal O(n\log n+q\log^2n)\)。

\(\mathcal{Code}\)

/*~Rainybunny~*/

#include <cstdio>
#include <vector>
#include <cassert> #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 int rint() {
int x = 0, f = 1, s = getchar();
for ( ; s < '0' || '9' < s; s = getchar() ) f = s == '-' ? -f : f;
for ( ; '0' <= s && s <= '9'; s = getchar() ) x = x * 10 + ( s ^ '0' );
return x * f;
} template<typename Tp>
inline void wint( Tp x ) {
if ( x < 0 ) putchar( '-' ), x = -x;
if ( 9 < x ) wint( x / 10 );
putchar( x % 10 ^ '0' );
} const int MAXN = 1e5, MAXQ = 6e5;
int type, n, M, q, ary[MAXN + 5]; inline int mul( const long long a, const int b ) { return a * b % M; }
inline int add( const long long a, const int b ) { return ( a + b ) % M; } struct Section {
int l, r, k, b;
inline bool operator < ( const Section& s ) const {
return l != s.l ? l < s.l : r < s.r;
}
};
typedef std::vector<Section> Atom; inline Atom mergeSec( const Atom& u, const Atom& v ) {
static Atom ret; ret.clear();
int i = 0, j = 0, las = 1, us = int( u.size() ), vs = int( v.size() );
while ( i < us && j < vs ) {
if ( u[i].r >= v[j].r ) {
ret.push_back( { las, v[j].r, mul( u[i].k, v[j].k ),
add( mul( v[j].k, u[i].b ), v[j].b ) } );
las = v[j].r + 1;
if ( u[i].r == v[j++].r ) ++i;
} else {
ret.push_back( { las, u[i].r, mul( u[i].k, v[j].k ),
add( mul( v[j].k, u[i].b ), v[j].b ) } );
las = u[i++].r + 1;
}
}
assert( las == n + 1 );
return ret;
} struct SegmentTree {
Atom sec[MAXQ << 2];
int upc[MAXQ << 2]; inline void insert( const int u, const int l, const int r,
const int x, const int i, const int j, const int a, const int b ) {
if ( l == r ) {
++upc[u];
if ( i > 1 ) sec[u].push_back( { 1, i - 1, 1, 0 } );
sec[u].push_back( { i, j, a, b } );
if ( j < n ) sec[u].push_back( { j + 1, n, 1, 0 } );
return ;
}
int mid = l + r >> 1;
if ( x <= mid ) insert( u << 1, l, mid, x, i, j, a, b );
else insert( u << 1 | 1, mid + 1, r, x, i, j, a, b );
if ( ( upc[u] = upc[u << 1] + upc[u << 1 | 1] ) == r - l + 1 ) {
sec[u] = mergeSec( sec[u << 1], sec[u << 1 | 1] );
}
} inline void query( const int u, const int l, const int r,
const int ql, const int qr, const int x, int& v ) {
if ( ql <= l && r <= qr ) {
int sid = std::upper_bound( sec[u].begin(), sec[u].end(),
Section{ x + 1, 0, 0, 0 } ) - sec[u].begin() - 1;
assert( 0 <= sid && sid < int( sec[u].size() ) );
assert( sec[u][sid].l <= x && x <= sec[u][sid].r );
v = add( mul( v, sec[u][sid].k ), sec[u][sid].b );
return ;
}
int mid = l + r >> 1;
if ( ql <= mid ) query( u << 1, l, mid, ql, qr, x, v );
if ( mid < qr ) query( u << 1 | 1, mid + 1, r, ql, qr, x, v );
}
} sgt; int main() {
type = rint() & 1, n = rint(), M = rint();
rep ( i, 1, n ) ary[i] = rint();
q = rint();
for ( int qid = 1, ans = 0, cnt = 0, op, i, j, a, b; qid <= q; ++qid ) {
op = rint(), i = rint(), j = rint(), a = rint();
if ( type ) i ^= ans, j ^= ans;
if ( op == 1 ) {
b = rint();
sgt.insert( 1, 1, q, ++cnt, i, j, a, b );
} else {
if ( type ) a ^= ans;
sgt.query( 1, 1, q, i, j, a, ans = ary[a] );
wint( ans ), putchar( '\n' );
}
}
return 0;
}

Solution -「UOJ #46」玄学的更多相关文章

  1. Solution -「UOJ #87」mx 的仙人掌

    \(\mathcal{Description}\)   Link.   给出含 \(n\) 个结点 \(m\) 条边的仙人掌图.\(q\) 次询问,每次询问给出一个点集 \(S\),求 \(S\) 内 ...

  2. Solution -「UOJ #450」复读机

    \(\mathcal{Description}\)   Link.   求从 \(m\) 种颜色,每种颜色无限多的小球里选 \(n\) 个构成排列,使得每种颜色出现次数为 \(d\) 的倍数的排列方案 ...

  3. Solution -「ARC 104E」Random LIS

    \(\mathcal{Description}\)   Link.   给定整数序列 \(\{a_n\}\),对于整数序列 \(\{b_n\}\),\(b_i\) 在 \([1,a_i]\) 中等概率 ...

  4. Solution -「UNR #5」「UOJ #671」诡异操作

    \(\mathcal{Desciprtion}\)   Link.   给定序列 \(\{a_n\}\),支持 \(q\) 次操作: 给定 \(l,r,v\),\(\forall i\in[l,r], ...

  5. Solution -「JOISC 2020」「UOJ #509」迷路的猫

    \(\mathcal{Decription}\)   Link.   这是一道通信题.   给定一个 \(n\) 个点 \(m\) 条边的连通无向图与两个限制 \(A,B\).   程序 Anthon ...

  6. Solution -「UR #21」「UOJ #632」挑战最大团

    \(\mathcal{Description}\)   Link.   对于简单无向图 \(G=(V,E)\),定义它是"优美"的,当且仅当 \[\forall\{a,b,c,d\ ...

  7. Solution -「UR #2」「UOJ #32」跳蚤公路

    \(\mathcal{Description}\)   Link.   给定一个 \(n\) 个点 \(m\) 条边的带权有向图,每条边还有属性 \(s\in\{-1,0,1\}\).对于每个 \(u ...

  8. Solution -「CTS 2019」「洛谷 P5404」氪金手游

    \(\mathcal{Description}\)   Link.   有 \(n\) 张卡牌,第 \(i\) 张的权值 \(w_i\in\{1,2,3\}\),且取值为 \(k\) 的概率正比于 \ ...

  9. Solution -「BZOJ 3812」主旋律

    \(\mathcal{Description}\)   Link.   给定含 \(n\) 个点 \(m\) 条边的简单有向图 \(G=(V,E)\),求 \(H=(V,E'\subseteq E)\ ...

随机推荐

  1. Go语言系列之标准库os

    os包提供了操作系统的系列函数,这些接口不依赖平台.设计为Unix风格的,错误处理是go风格的:调用失败会返回错误值而非错误码.通常错误值里包含更多信息. os包的接口在所有操作系统中都是一致的.非公 ...

  2. JuiceFS 即将发布 1.0 并调整开源许可

    开源一周年 JuiceFS 开始于 2017 年,是一款云原生分布式文件系统,旨在帮助企业解决多云.跨云.混合云环境下所面临的诸多挑战:数据安全和保护.大数据架构升级.海量小文件访问.Kubernet ...

  3. 痞子衡嵌入式:在IAR开发环境下将整个源文件代码重定向到任意RAM中的方法

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家分享的是在IAR开发环境下将整个源文件代码重定向到任意RAM中的方法. 痞子衡旧文 <在IAR下将关键函数重定向到RAM中执行的方法> ...

  4. Javascript中定时器的使用方法

    Javascript中定时器的使用方法 1.间隔定时器(每隔一段时间执行一次代码) 格式:setInterval(函数,时间) //时间单位是毫秒,每隔设置的时间执行函数里的内容一遍(一直执行) // ...

  5. MySQL查询处理——逻辑查询处理和物理查询处理

    对于查询处理,可将其分为逻辑查询处理和物理查询处理.逻辑查询处理表示执行查询应该产生什么样的结果,而物理查询代表MySQL数据库是如何得到结果的. 逻辑查询处理 MySQL真正的执行顺序如下: (8) ...

  6. tarjan全家桶

    tarjan 全家桶 关于tarjan 它太强了 CCCOrz dfs树&low dfs树:在图上做不重复经过同一点的dfs,经过的边与点形成一棵树.于是图上所有点都被这棵树包含,一部分边被包 ...

  7. 集合框架-Map集合-HashMap存储自定义对象

    1 package cn.itcast.p6.hashmap.demo; 2 3 import java.util.HashMap; 4 import java.util.Iterator; 5 im ...

  8. 传统的DOM渲染方式?

    1.什么是DOM渲染? 所谓的DOM渲染是指的是对于浏览器中展现给用户的DOM文档的生成的过程. 2.DOM渲染的过程,大致可以分为三个阶段: --纯后端渲染 --纯前端渲染 --服务端的JS渲染结合 ...

  9. IBM MQ常用运维命令

    创建队列管理器 crtmqm –q QMgrName -q是指创建缺省的队列管理器 删除队列管理器 dltmqm QmgrName 启动队列管理器 strmqm QmgrName 如果是启动默认的队列 ...

  10. static关键字的一些使用

    百度百科定义static关键字 通常情况下,类成员必须通过它的类的对象访问,但是可以创建这样一个成员,它能够被它自己使用,而不必引用特定的实例.在成员的声明前面加上关键字static(静态的)就能创建 ...