Codeforces 679E - Bear and Bad Powers of 42(线段树+势能分析)
这个 \(42\) 的条件非常奇怪,不过注意到本题 \(a_i\) 范围的最大值为 \(10^{14}\),而在值域范围内 \(42\) 的幂的个数最多只有 \(13\) 个,故考虑用类似于 seg-beats 的方法解决这道题。
首先不考虑操作 \(2\)(区间赋值操作),我们很容易发现一个性质,那就是我们对一个区间进行区间加的操作,每额外进行一次,都是因为存在某个数 \(a_i\) 达到了 \(42\) 的整数次幂,而我们的 \(a_i\) 是单调递增的,故每个数最多只可能出现 \(13\) 次成为 \(42\) 的整数次幂的时刻,故总操作次数最多只有 \(1.3\times 10^6\),于是暴力加是不会出问题的。故现在问题转化为怎样求一个区间中是否存在 \(42\) 的整数次幂。
考虑记 \(b_i\) 为 \(\geq a_i\) 的最小的 \(42\) 的整数次幂。显然我们对区间进行 \(+v\) 操作相当于将对应区间 \(b_i-a_i\) 的值 \(-v\),这个操作可以用线段树维护。当然,我们进行一次 \(-v\) 操作后会导致某些 \(b_i-a_i\) 变成负数,也就是说,此时的 \(b_i\) 不再是 \(\geq a_i\) 的最小的 \(42\) 的整数次幂了,我们对于这样的 \(i\) 暴力修改 \(b_i\) 的值,具体来说,线段树维护 \(b_i-a_i\) 的最小值,每次修改后在线段树上进行一遍递归,当递归到某个区间时若该区间 \(b_i-a_i\) 的最小值 \(\geq 0\) 则意味着不存在 \(b_i-a_i<0\) 的 \(i\),直接 return
就行了,否则继续递归左右儿子,递归到叶子节点直接把值改掉。由之前的分析可知最多修改次数也是 \(1.3\times 10^6\),如此暴力进行下去直到全局 \(b_i-a_i\) 不为 \(0\)(不存在 \(a_i=b_i\))即可,复杂度 \(q\log_{42}(qa_i)\log n\)。
接下来考虑加上区间赋值操作之后怎么处理。由于我们有区间赋值操作,故刚才总操作次数 \(1.3\times 10^6\) 的复杂度上界就不再存在了(不过听说按照之前的套路暴力赋值也能过?大概是因为这题数据比较难卡罢)。不过作为精益求精的 OIer,我们要思考更优秀的做法。不难发现进行一遍区间赋值之后会使很多位置上的值变成同一个值,也就是说我们区间赋值操作会将序列划分成一段段,我们考虑用 multiset
维护每一段的右端点,这样查询的时候只用查询对应位置所在段的右端点的值即可。
具体来说,初始状态下所有元素都单独成段,也就是每个元素都是对应段的右端点。当我们进行 \(2\) 操作的时候,相当于 \([l,r]\) 成为了完整的一段,故我们将 multiset
中 \([l,r-1]\) 内的元素全部删除并插入 \(r\),由于我们只关心段的右端点的值即可,于是我们将线段树 \([l,r-1]\) 位置上赋上 INF(为了保证它们永远不会变成负数),暂且忽略它们的存在,并将 \(r\) 位置上的值改为待赋的值。当然,这样也会导致 \(l-1\) 成为新的段的右端点,故在 multiset
中插入 \(l-1\),并将 \(l-1\) 位置上的值改为真实值(原本 \(l-1\) 所在段的右端点的值)即可。其余都和不考虑操作 \(2\) 的版本一样。
复杂度还是 \(q\log_{42}(qa_i)\log n\)。
#include <bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define fill0(a) memset(a,0,sizeof(a))
#define fill1(a) memset(a,-1,sizeof(a))
#define fillbig(a) memset(a,63,sizeof(a))
#define pb push_back
#define ppb pop_back
#define mp make_pair
template<typename T1,typename T2> void chkmin(T1 &x,T2 y){if(x>y) x=y;}
template<typename T1,typename T2> void chkmax(T1 &x,T2 y){if(x<y) x=y;}
typedef pair<int,int> pii;
typedef long long ll;
typedef unsigned int u32;
typedef unsigned long long u64;
namespace fastio{
#define FILE_SIZE 1<<23
char rbuf[FILE_SIZE],*p1=rbuf,*p2=rbuf,wbuf[FILE_SIZE],*p3=wbuf;
inline char getc(){return p1==p2&&(p2=(p1=rbuf)+fread(rbuf,1,FILE_SIZE,stdin),p1==p2)?-1:*p1++;}
inline void putc(char x){(*p3++=x);}
template<typename T> void read(T &x){
x=0;char c=getchar();T neg=0;
while(!isdigit(c)) neg|=!(c^'-'),c=getchar();
while(isdigit(c)) x=(x<<3)+(x<<1)+(c^48),c=getchar();
if(neg) x=(~x)+1;
}
template<typename T> void recursive_print(T x){if(!x) return;recursive_print(x/10);putc(x%10^48);}
template<typename T> void print(T x){if(!x) putc('0');if(x<0) putc('-'),x=~x+1;recursive_print(x);}
void print_final(){fwrite(wbuf,1,p3-wbuf,stdout);}
}
const int MAXN=1e5;
const int LOG_42=13;
const ll INF=1e18;
int n,qu;set<int> st;
ll pw42[LOG_42+2];
ll get42(ll v){return *lower_bound(pw42,pw42+LOG_42+1,v);}
struct node{int l,r;ll v,tag_lz,add_lz;} s[MAXN*4+5];
ll a[MAXN+5],nxt42[MAXN+5];
void pushup(int k){s[k].v=min(s[k<<1].v,s[k<<1|1].v);}
void pushdown(int k){
if(s[k].tag_lz!=0){
s[k<<1].v=s[k].tag_lz;s[k<<1|1].v=s[k].tag_lz;
s[k<<1].tag_lz=s[k].tag_lz;s[k<<1|1].tag_lz=s[k].tag_lz;
s[k].tag_lz=0;
}
if(s[k].add_lz!=0){
s[k<<1].v+=s[k].add_lz;s[k<<1|1].v+=s[k].add_lz;
s[k<<1].add_lz+=s[k].add_lz;s[k<<1|1].add_lz+=s[k].add_lz;
s[k].add_lz=0;
}
}
void build(int k,int l,int r){
s[k].l=l;s[k].r=r;
if(l==r){nxt42[l]=get42(a[l]);s[k].v=nxt42[l]-a[l];return;}
int mid=l+r>>1;build(k<<1,l,mid);build(k<<1|1,mid+1,r);
pushup(k);
}
void assign(int k,int l,int r,ll x){
if(l<=s[k].l&&s[k].r<=r){s[k].tag_lz=s[k].v=x;return;}
pushdown(k);int mid=s[k].l+s[k].r>>1;
if(r<=mid) assign(k<<1,l,r,x);
else if(l>mid) assign(k<<1|1,l,r,x);
else assign(k<<1,l,r,x),assign(k<<1|1,mid+1,r,x);
pushup(k);
}
void change_v(int k,int p,ll x){
if(s[k].l==s[k].r){
nxt42[s[k].l]=get42(x);s[k].v=nxt42[s[k].l]-x;return;
} pushdown(k);int mid=s[k].l+s[k].r>>1;
if(p<=mid) change_v(k<<1,p,x);
else change_v(k<<1|1,p,x);
pushup(k);
}
void add(int k,int l,int r,ll x){
if(l<=s[k].l&&s[k].r<=r){s[k].add_lz+=x;s[k].v+=x;return;}
pushdown(k);int mid=s[k].l+s[k].r>>1;
if(r<=mid) add(k<<1,l,r,x);
else if(l>mid) add(k<<1|1,l,r,x);
else add(k<<1,l,r,x),add(k<<1|1,mid+1,r,x);
pushup(k);
}
void killneg(int k){
if(s[k].v>=0) return;
if(s[k].l==s[k].r){
s[k].v=nxt42[s[k].l]-s[k].v;
nxt42[s[k].l]=get42(s[k].v);
s[k].v=nxt42[s[k].l]-s[k].v;
return;
} pushdown(k);killneg(k<<1);killneg(k<<1|1);
pushup(k);
}
ll getdif(int k,int p){
if(s[k].l==s[k].r) return s[k].v;
int mid=s[k].l+s[k].r>>1;pushdown(k);
if(p<=mid) return getdif(k<<1,p);
else return getdif(k<<1|1,p);
}
ll query(int k,int p){
if(s[k].l==s[k].r) return nxt42[s[k].l]-s[k].v;
int mid=s[k].l+s[k].r>>1;pushdown(k);
if(p<=mid) return query(k<<1,p);
else return query(k<<1|1,p);
}
void split(int x){
int nxt=*st.lower_bound(x);
if(nxt==x) return;st.insert(nxt);
change_v(1,x,query(1,nxt));st.insert(x);
}
int main(){
pw42[0]=1;for(int i=1;i<=LOG_42;i++) pw42[i]=pw42[i-1]*42ll;
scanf("%d%d",&n,&qu);
for(int i=1;i<=n;i++) scanf("%lld",&a[i]),st.insert(i);
build(1,1,n);
while(qu--){
int opt;scanf("%d",&opt);
if(opt==1){int x;scanf("%d",&x);printf("%lld\n",query(1,*st.lower_bound(x)));}
else if(opt==2){
int l,r,v;scanf("%d%d%d",&l,&r,&v);
if(l>1) split(l-1);split(r);
st.erase(st.lower_bound(l),st.lower_bound(r));
if(l<r) assign(1,l,r-1,INF);
change_v(1,r,v);
} else {
int l,r,v;scanf("%d%d%d",&l,&r,&v);
if(l>1) split(l-1);split(r);
do {
add(1,l,r,-v);killneg(1);
} while(s[1].v==0);
}
}
return 0;
}
/*
6 13
40 1700 7 1672 4 1722
3 2 4 42
1 2
1 3
1 4
3 2 6 50
1 2
1 4
1 6
2 3 4 41
3 1 5 1
1 1
1 3
1 5
*/
Codeforces 679E - Bear and Bad Powers of 42(线段树+势能分析)的更多相关文章
- codeforces 679e Bear and Bad Powers of 42
传送门:http://codeforces.com/contest/679/problem/E 题目意思很清晰,给你一个序列,要求你完成以下三个操作: 1.输出A[i] 2.将[a,b]区间的所有数字 ...
- Lucky Array Codeforces - 121E && Bear and Bad Powers of 42 Codeforces - 679E
http://codeforces.com/contest/121/problem/E 话说这题貌似暴力可A啊... 正解是想出来了,结果重构代码,调了不知道多久才A 错误记录: 1.线段树搞混num ...
- DZY Loves Colors CodeForces - 444C (线段树势能分析)
大意:有$n$个格子, 初始$i$位置的颜色为$i$, 美丽值为0, 有两种操作 将区间$[l,r]$内的元素全部改为$x$, 每个元素的美丽值增加$|x-y|$, $y$为未改动时的值 询问区间$[ ...
- CF679E Bear and Bad Powers of 42
一段时间不写线段树标记,有些生疏了 codeforces 679e Bear and Bad Powers of 42 - CHADLZX - 博客园 关键点是:42的次幂,在long long范围内 ...
- [Codeforces 464E] The Classic Problem(可持久化线段树)
[Codeforces 464E] The Classic Problem(可持久化线段树) 题面 给出一个带权无向图,每条边的边权是\(2^{x_i}(x_i<10^5)\),求s到t的最短路 ...
- Codeforces679E. Bear and Bad Powers of 42
传送门 今天子帧的一套模拟题的T3. 考试的时候其实已经想到了正解了,但是一些地方没有想清楚,就没敢写,只打了个暴力. 首先考虑用线段树维护区间信息. 先把每个值拆成两个信息,一是距离他最近的且大于他 ...
- Educational Codeforces Round 6 E. New Year Tree dfs+线段树
题目链接:http://codeforces.com/contest/620/problem/E E. New Year Tree time limit per test 3 seconds memo ...
- Codeforces Round #244 (Div. 2) B. Prison Transfer 线段树rmq
B. Prison Transfer Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/problemset/pro ...
- codeforces 893F - Physical Education Lessons 动态开点线段树合并
https://codeforces.com/contest/893/problem/F 题意: 给一个有根树, 多次查询,每次查询对于$x$i点的子树中,距离$x$小于等于$k$的所有点中权值最小的 ...
随机推荐
- IT行业供应过剩?“减负路线”助你成为人人都想要的抢手开发
开发者的IT技能:良莠不齐,优秀的软件开发人员在招聘时往往可遇不可求.包括国家统计局在内的多家权威机构的报告提示,在数字化转型的浪潮下,市场对于软件开发人员的需求数量已经远远地超过现有开发者群体的数量 ...
- (翻译)领域驱动设计实现-Implementing Domain Driven Design
简介 Implementing Domain Driven Design 领域驱动设计实现 A practical guide for implementing the Domain Driven D ...
- IEEE754浮点数的转换
将十进制数转换为单精度浮点数 如何将十进制数转换为单精度浮点数参考 首先要知道 IEEE浮点标准:V=(-1)^s * M * 2^E 1.符号(sign)s决定这个数是负数(s=1)还是正数,0(s ...
- Hadoop MapReduce 保姆级吐血宝典,学习与面试必读此文!
Hadoop 涉及的知识点如下图所示,本文将逐一讲解: 本文档参考了关于 Hadoop 的官网及其他众多资料整理而成,为了整洁的排版及舒适的阅读,对于模糊不清晰的图片及黑白图片进行重新绘制成了高清彩图 ...
- 【c++ Prime 学习笔记】第15章 面向对象程序设计
15.1 OOP:概述 面向对象程序设计(object-oriented programming)的核心思想是:数据抽象.继承.动态绑定 使用数据抽象,可将类的接口与实现分离 使用继承,可定义相似的类 ...
- kivy画个半圆
from kivy.uix.boxlayout import BoxLayout from kivy.app import App class BoxLayoutWidget(BoxLayout): ...
- OO_JAVA_表达式求导
OO_JAVA_表达式求导_第一弹 ---------------------------------------------------表达式提取部分 词法分析 首先,每一个表达式内部都存在不可 ...
- stm32串口学习笔记
stm32作为现在嵌入式物联网单片机行业中经常要用多的技术,相信大家都有所接触,今天这篇就给大家详细的分析下有关于stm32的出口,还不是很清楚的朋友要注意看看了哦,在最后还会为大家分享有些关于stm ...
- Java之父 James Gosling 发表博文 《Too Soon》纪念乔布斯。
几个礼拜前,我们还在讨论乔布斯的辞职.虽然我们都知道这意味着什么,但是我没有想到一切来的如此之快.已经有很多关于这件事情的文章了,特别是"经济学人"的这篇文章. 乔布斯是一个很独特 ...
- centos7 二进制安装mysql-8.0.19
安装包下载地址:https://dev.mysql.com/get/Downloads/MySQL-8.0/mysql-8.0.19-linux-glibc2.12-x86_64.tar.xz 1.检 ...