Solution -「UNR #5」「UOJ #671」诡异操作
\(\mathcal{Desciprtion}\)
Link.
给定序列 \(\{a_n\}\),支持 \(q\) 次操作:
- 给定 \(l,r,v\),\(\forall i\in[l,r],~a_i\leftarrow\lfloor\frac{a_i}{v}\rfloor\);
- 给定 \(l,r,v\),\(\forall i\in[l,r],~a_i\leftarrow a_i\otimes v\),其中 \(\otimes\) 表示二进制按位与;
- 给定 \(l,r\),求 \(\sum_{i=l}^ra_i\)。
\(n\le3\times10^5\),\(q\le2\times10^5\),值域 \(V<2^{128}\),答案对 __uint128_t 自然溢出。
\(\mathcal{Solution}\)
写个“暴力”,证明复杂度,得到正解√
不考虑 (1) 操作,想想如何支持区间与-区间求和。我们用一棵线段树来维护,对于一个长为 \(s\) 的区间,维护一个表格 \(S_{0..\log s}\),设某个 bit \(x\) 在该区间中出现了 \(c\) 次,则在 \(S\) 中每个 \(c\) 的 bit 处加上 \(x\) 的贡献。可以发现 \(\sum S_i2^i\) 就是区间和,合并类似高精度加法做到 \(\mathcal O(s)\),而区间与直接在令 \(S_i\leftarrow S_i\otimes v\) 即可解决,也是 \(\mathcal O(s)\)。不失为一种奇怪的小 trick√
取整除,自然而然暴力做。那么至多遍历 \(\omega=\log V\) 次线段树,乘上 \(\mathcal O(s)\)(\(s\) 为区间长度)的上传代价,遍历整棵树的上传代价和式 \(T(n)=2T(n/2)+\log n=\mathcal O(n)\),所以总复杂度 \(\mathcal O(\omega n)\),加上区间与和求答案,最终复杂度 \(\mathcal O(q\log^2n+\omega n)\)。
\(\mathcal{Code}\)
用 template 实现线段树√
/*~Rainybunny~*/
#include <set>
#include <cmath>
#include <cstdio>
#include <cassert>
#include <cstring>
#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 )
typedef __uint128_t UI;
inline UI rxint() {
static char buf[100]; scanf( "%s", buf );
UI ret = 0;
for ( int i = 0; buf[i]; ++i ) {
ret = ret << 4 | ( buf[i] <= '9' ? buf[i] ^ '0' : buf[i] - 'a' + 10 );
}
return ret;
}
inline int rdint() {
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;
}
inline void wxint( const UI x ) {
if ( x >= 16 ) wxint( x >> 4 );
putchar( ( x & 15 ) >= 10 ? 'a' + ( x & 15 ) - 10 : '0' ^ ( x & 15 ) );
}
inline int imax( const int a, const int b ) { return a < b ? b : a; }
const int MAXN = 3e5, MAXQ = 2e5;
int n, q;
template<const int H>
struct Atom {
UI val[H + 1];
inline UI& operator [] ( const int k ) { return val[k]; }
friend inline Atom<H + 1> operator + ( Atom<H>& u, Atom<H>& v ) {
static Atom<H + 1> ret;
ret[0] = u[0] ^ v[0]; UI up = u[0] & v[0];
rep ( i, 1, H ) {
ret[i] = up ^ u[i] ^ v[i];
up = ( up & u[i] ) | ( up & v[i] ) | ( u[i] & v[i] );
}
ret[H + 1] = up;
return ret;
}
inline Atom& operator &= ( const UI& x ) {
rep ( i, 0, H ) val[i] &= x;
return *this;
}
inline UI get() const {
UI ret = 0;
rep ( i, 0, H ) ret += val[i] << i;
return ret;
}
};
template<const int H>
struct SegmentTree {
Atom<H> sum; bool zero; UI tag;
SegmentTree<H - 1> lch, rch;
inline void pushup() {
sum = lch.sum + rch.sum, zero = lch.zero && rch.zero;
}
inline void pushan( const UI& v ) {
tag &= v, sum &= v;
}
inline void pushdn() {
if ( ~tag ) {
lch.pushan( tag ), rch.pushan( tag );
tag = ~UI( 0 );
}
}
inline void build( const int l, const int r ) {
int mid = l + r >> 1; tag = ~UI( 0 );
lch.build( l, mid ), rch.build( mid + 1, r );
pushup();
}
inline void secAnd( const int l, const int r,
const int ql, const int qr, const UI& v ) {
if ( zero ) return ;
if ( ql <= l && r <= qr ) return void( pushan( v ) );
int mid = l + r >> 1; pushdn();
if ( ql <= mid ) lch.secAnd( l, mid, ql, qr, v );
if ( mid < qr ) rch.secAnd( mid + 1, r, ql, qr, v );
pushup();
}
inline void secDiv( const int l, const int r,
const int ql, const int qr, const UI& v ) {
if ( zero || v == 1 ) return ;
if ( l == r ) return void( zero = !( sum[0] /= v ) );
int mid = l + r >> 1; pushdn();
if ( ql <= mid ) lch.secDiv( l, mid, ql, qr, v );
if ( mid < qr ) rch.secDiv( mid + 1, r, ql, qr, v );
pushup();
}
inline UI query( const int l, const int r, const int ql, const int qr ) {
if ( zero ) return 0;
if ( ql <= l && r <= qr ) return sum.get();
int mid = l + r >> 1; UI ret = 0; pushdn();
if ( ql <= mid ) ret += lch.query( l, mid, ql, qr );
if ( mid < qr ) ret += rch.query( mid + 1, r, ql, qr );
return ret;
}
};
template<>
struct SegmentTree<0> {
Atom<0> sum; bool zero; UI tag;
inline void pushan( const UI& v ) { tag &= v, sum &= v; }
inline void build( const int l, const int r ) {
assert( l == r );
tag = ~UI( 0 ), zero = !( sum[0] = r < n ? rxint() : 0 );
}
inline void secAnd( const int l, const int r,
const int ql, const int qr, const UI& v ) {
if ( zero ) return ;
assert( ql <= l && r <= qr ), pushan( v );
}
inline void secDiv( const int l, const int r,
const int ql, const int qr, const UI& v ) {
if ( zero || v == 1 ) return ;
zero = !( sum[0] /= v );
}
inline UI query( const int l, const int r, const int ql, const int qr ) {
if ( zero ) return 0;
return assert( ql <= l && r <= qr ), sum.get();
}
};
SegmentTree<19> sgt;
int main() {
// freopen( "machine.in", "r", stdin );
// freopen( "machine.out", "w", stdout );
n = rdint(), q = rdint();
int R = 1 << 19;
sgt.build( 0, R - 1 );
for ( int op, l, r; q--; ) {
op = rdint(), l = rdint() - 1, r = rdint() - 1;
if ( op == 1 ) sgt.secDiv( 0, R - 1, l, r, rxint() );
else if ( op == 2 ) sgt.secAnd( 0, R - 1, l, r, rxint() );
else wxint( sgt.query( 0, R - 1, l, r ) ), putchar( '\n' );
}
return 0;
}
Solution -「UNR #5」「UOJ #671」诡异操作的更多相关文章
- 「UNR#2」黎明前的巧克力
「UNR#2」黎明前的巧克力 解题思路 考虑一个子集 \(S\) 的异或和如果为 \(0\) 那么贡献为 \(2^{|S|}\) ,不难列出生产函数的式子,这里的卷积是异或卷积. \[ [x^0]\p ...
- 「UNR#1」奇怪的线段树
「UNR#1」奇怪的线段树 一道好题,感觉解法非常自然. 首先我们只需要考虑一次染色最下面被包含的那些区间,因为把无解判掉以后只要染了一个节点,它的祖先也一定被染了.然后发现一次染色最下面的那些区间一 ...
- Solution -「CTS 2019」「洛谷 P5404」氪金手游
\(\mathcal{Description}\) Link. 有 \(n\) 张卡牌,第 \(i\) 张的权值 \(w_i\in\{1,2,3\}\),且取值为 \(k\) 的概率正比于 \ ...
- Solution -「LGR-087」「洛谷 P6860」象棋与马
\(\mathcal{Description}\) Link. 在一个 \(\mathbb R^2\) 的 \((0,0)\) 处有一颗棋子,对于参数 \(a,b\),若它当前坐标为 \((x ...
- 「题解」「美团 CodeM 资格赛」跳格子
目录 「题解」「美团 CodeM 资格赛」跳格子 题目描述 考场思路 思路分析及正解代码 「题解」「美团 CodeM 资格赛」跳格子 今天真的考自闭了... \(T1\) 花了 \(2h\) 都没有搞 ...
- 【翻译】西川善司的「实验做出的游戏图形」「GUILTY GEAR Xrd -SIGN-」中实现的「纯卡通动画的实时3D图形」的秘密,后篇
http://www.4gamer.net/games/216/G021678/20140714079/ 连载第2回的本回, Arc System Works开发的格斗游戏「GUILTY G ...
- Android内存管理(4)*官方教程 含「高效内存的16条策略」 Managing Your App's Memory
Managing Your App's Memory In this document How Android Manages Memory Sharing Memory Allocating and ...
- SSH连接时出现「WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!」解决办法
用ssh來操控github,沒想到連線時,出現「WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!」,後面還有一大串英文,這時當然要向Google大神求助 ...
- 「Windows MFC 」「Edit Control」 控件
「Windows MFC 」「Edit Control」 控件
随机推荐
- Mysql字符串字段判断是否包含某个字符串的方法
方法一:like SELECT * FROM 表名 WHERE 字段名 like "%字符%"; 方法二:find_in_set() 利用mysql 字符串函数 find_in_s ...
- VMware 创建的虚拟机,Xshell无法进行连接
使用场景: 在VMware 创建了Centos7后,Xshell一直连接不上,如果排查以下问题还是不行.就可以用这种方法了 1.配置了静态地址 2.VMware配置了NAT映射,划分了网段后 3.检查 ...
- test_6 python的列表去重
1.使用内置函数set() set() 函数创建一个无序不重复元素集,可进行关系测试,删除重复数据,还可以计算交集.差集.并集等. 2.创建一个空的列表进行比较,把不重复的元素添加到新的列表中 #co ...
- JDK8 一文搞定👍
! https://zhuanlan.zhihu.com/p/442182870 Java8 新特性 学习来源于 B站 尚硅谷yyds Java学习源码 2021/11/22 距离,过年还有 57 天 ...
- CTF-sql-万能密码
以下是我在学习sql注入时的一些感想分享,希望能帮助到大家,如有错误,望指出. 万能密码的种类: ①select * from admin where username ="" a ...
- spring拦截机制中Filter(过滤器)、interceptor(拦截器)和Aspect(切面)的使用及区别
Spring中的拦截机制,如果出现异常的话,异常的顺序是从里面到外面一步一步的进行处理,如果到了最外层都没有进行处理的话,就会由tomcat容器抛出异常. 1.过滤器:Filter :可以获得Http ...
- 关于网页中鼠标动作 onfocus onblur focus()
其中: onFocus事件就是当光标落在文本框中时发生的事件. onBlur事件是光标失去焦点时发生的事件. 例如: <textarea onfocus="if(hello') {va ...
- K8s PV and PVC and StorageClass
PVC和PV之间没有依靠ID.名称或者label匹配,而是靠容量和访问模式,PVC的容量和访问模式需要是某个PV的子集才能自动匹配上.注意:PVC和PV是一对一的,也即一个PV被一个PVC自动匹配后, ...
- CPU飙升排查
怎么排查CPU飙升 线上有些系统,本来跑的好好的,突然有一天就会出现报警,CPU使用率飙升,然后重启之后就好了.例如,多线程操作一个线程不安全的list往往就会出现这种现象.那么怎么定位到具体的代码范 ...
- 【存】008 Linux 文件查找 find
01 一起来认识 find! 在 Linux 系统,find 毫无疑问是最强的文件查找工具.find 一般会与其他命令结合,将查找到的结果作为参数传入到后置命令中,进行删除.统计.复制迁移等操作. 0 ...