洛谷P4891 序列(势能线段树)
闲话
考场上一眼看出这是个毒瘤线段树准备杠题,发现实在太难调了,被各路神犇虐哭qwq
考后看到各种优雅的暴力AC。。。。。。宝宝心里苦qwq
思路分析
题面里面是一堆乱七八糟的限制和性质,这时候需要冷静想想有没有可利用的地方。蒟蒻一开始往势能线段树上面想了想。
定义一个全局势能函数,为所有\(C_i<B_i\)的位置个数。注意两个操作的修改都不会小于原来的数。
一个是改\(A\),相当于对\(C\)进行区间设置,此时我们每暴力找到一个原来\(C_i<B_i\)但是现在\(C_i\ge y\)的位置,就需要在线段树内跳\(\log\)层,再修改,势能函数就会下降。如果碰到那些修改以后对势能没有影响的子区间,就跳过而不继续暴力递归下去。
一个是改\(B\),是单点修改,线段树内跳\(\log\)层,势能函数至多加\(1\)。
于是,如果我们能够维护信息,从而判断和控制哪里该暴力递归、哪里该跳过的话,我们总的在线段树内跳的次数不会超过\((n+q)\log n\)。
下面用a代替了\(C\),b代替了\(B\)。蒟蒻在线段树里维护了:
- pa:区间所有a<b的位置的a的积
- pb:区间所有a>=b的位置的b的积
- ma:区间a的最大值
- mb:区间所有a<b的位置的b的最小值,没有则设成INF
- cnt:区间所有a<b的位置的总数
- la:bool型变量,区间设置懒标记
修改a的时候,利用单调不降的性质,我们在线段树上先通过二分来对需要修改的若干个子树进行定位。对于当前子区间,如果当前设置值\(y\)比mb要小,那么设置对答案没有影响,直接打上区间设置标记后退出;否则继续递归直到找到叶子节点,进行修改后退出。
修改b就比较轻松,只要找到对应的叶子节点改完后一路回溯即可。
很多事都是说起来容易做起来难,这题也不例外。调试几乎花了整个晚上。要注意的细节很多,也只好自己仔细思考了。
时间复杂度\(O(n\log n+q\log^2n)\),上界很松。多出来的\(\log\)是区间改a时需要快速幂更新pa造成的。
跑了不到200ms,比什么树套树、分块还是要好看一点,但是被暴力碾压也是有点无奈啊~
#include<bits/stdc++.h>
#define RG register
#define R RG int
#define I inline
#define G if(++ip==ie)fread(ip=buf,1,N,stdin)
using namespace std;
typedef long long LL;
const LL N=1<<18,YL=1e9+7;
char buf[N],*ie=buf+N,*ip=ie-1;
int y,a[N];
I int in(){
G;while(*ip<'-')G;
R x=*ip&15;G;
while(*ip>'-'){x*=10;x+=*ip&15;G;}
return x;
}
I LL qpow(RG LL b,R k){//快速幂
RG LL a=1;
for(;k;k>>=1,(b*=b)%=YL)
if(k&1)(a*=b)%=YL;
return a;
}
struct Node{//个人认为写指针比较直观(貌似immortalCO也有这样的看法)
Node*lc,*rc;bool la;
LL pa,pb;int l,r,m,ma,mb,cnt;
I void up(){//上传
pa=lc->pa*rc->pa%YL;
pb=lc->pb*rc->pb%YL;
ma=max(lc->ma,rc->ma);
mb=min(lc->mb,rc->mb);
cnt=lc->cnt+rc->cnt;
}
I void dn(){//下传区间设置标记
if(la){
lc->ma=rc->ma=ma;
lc->la=rc->la=1;la=0;
lc->pa=qpow(ma,lc->cnt);
rc->pa=qpow(ma,rc->cnt);
}
}
I void build(R s,R e){//建树
l=s;r=e;m=(s+e)>>1;la=0;
if(s==e){
ma=a[l];mb=in();
(cnt=ma<mb)?(pa=ma,pb=1):(pa=1,pb=mb,mb=YL);
return;
}
(lc=new Node)->build(l,m);
(rc=new Node)->build(m+1,r);
this->up();
}
I void upda(){//区间修改a
if(y<mb){//对区间势能没有影响
pa=qpow(ma=y,cnt);la=1;
return;
}
if(l==r){//到了叶子节点
ma=y;pa=1;pb=mb;mb=YL;
return;
}
this->dn();
lc->upda();rc->upda();
this->up();
}
I void updb(R s){//单点更新b
if(l==r){//仔细判断三种情况再修改
if(ma<pb)mb=y;
else if(ma<y)pa=ma,pb=cnt=1,mb=y;
else pb=y;
return;
}
this->dn();
(s<=m?lc:rc)->updb(s);
this->up();
}
I void bound(R s){//线段树二分定位,注意细节
if(s==l&&ma<y)return this->upda();
if(l==r)return;
this->dn();
if(lc->ma<y)rc->bound(m+1);
lc->bound(s);
this->up();
}
};
int main(){
R n=in(),q=in(),op,x;
for(R i=1;i<=n;++i)a[i]=max(a[i-1],in());
RG Node rt;rt.build(1,n);
while(q--){
op=in();x=in();y=in();
op?rt.updb(x):rt.bound(x);
printf("%lld\n",rt.pa*rt.pb%YL);
}
return 0;
}
洛谷P4891 序列(势能线段树)的更多相关文章
- 洛谷P4891 序列 || 膜法阵,魔法阵
https://www.luogu.org/problemnew/show/P4891 一道几乎一样的题http://210.33.19.103/contest/1130/problem/3 题面ht ...
- 【BZOJ】1012: [JSOI2008]最大数maxnumber /【洛谷】1198(线段树)
Description 现在请求你维护一个数列,要求提供以下两种操作:1. 查询操作.语法:Q L 功能:查询当前数列中末尾L个数中的最大的数,并输出这个数的值.限制:L不超过当前数列的长度.2. 插 ...
- 洛谷题解P4314CPU监控--线段树
题目链接 https://www.luogu.org/problemnew/show/P4314 https://www.lydsy.com/JudgeOnline/problem.php?id=30 ...
- 洛谷P3372/poj3468(线段树lazy_tag)(询问区间和,支持区间修改)
洛谷P3372 //线段树 询问区间和,支持区间修改 #include <cstdio> using namespace std; struct treetype { int l,r; l ...
- BZOJ2141&洛谷1975 排队 【线段树套treap】
题目 排排坐,吃果果,生果甜嗦嗦,大家笑呵呵.你一个,我一个,大的分给你,小的留给我,吃完果果唱支歌,大家乐和和. 红星幼儿园的小朋友们排起了长长地队伍,准备吃果果.不过因为小朋友们的身高有所区别,排 ...
- 【洛谷P2894】Hotel 线段树+二分查询
题目大意:给定一个长度为 N 的序列,每个点有两种状态 1/0,表示占有和空闲,现支持 first-fit 查询是否有一段连续的长度为 X 的空闲子序列和区间赋值操作. 题解:get到了线段树新技能. ...
- 洛谷P4065 [JXOI2017]颜色(线段树)
题意 题目链接 Sol 线段树板子题都做不出来,真是越来越菜了.. 根据题目描述,一个合法区间等价于在区间内的颜色没有在区间外出现过. 所以我们可以对于每个右端点,统计最长的左端点在哪里,刚开始以为这 ...
- 洛谷P5111 zhtobu3232的线段树
题意:给定线段树,上面若干个节点坏了,求能表示出多少区间. 区间能被表示出当且仅当拆出来的log个节点都是好的. 解:每个区间在最浅的节点处计算答案. 对于每个节点维护从左边过来能有多少区间,从右边过 ...
- 洛谷P3960 列队 NOIp2017 线段树/树状数组/splay
正解:动态开点线段树 解题报告: 传送门! 因为最近学主席树的时候顺便get到了动态开点线段树?刚好想起来很久很久以前就想做结果一直麻油做的这题,,,所以就做下好了QAQ 然后说下,这题有很多种方法, ...
随机推荐
- 关于XLL加载项动态加载、卸载的演示及XLL函数自定义类型注册的演示
1.在XLL中,把函数定义成不同的类型,在Excel中的实际效果也不同,具体如下: pxMacroType value ...
- 为什么HashMap初始大小为16,为什么加载因子大小为0.75,这两个值的选取有什么特点?
先看HashMap的定义: public class HashMap<K,V>extends AbstractMap<K,V>implements Map<K,V> ...
- Java 数据库操作
目录 Java数据库组织架构 下载驱动包 连接数据库 连接数据库的三个步骤 连接数据库的高开销 Statement接口介绍 PreparedStatement类 使用PreparedStatement ...
- .net WCF WF4.5
花了两天时间学习使用WF,把一些遇到的问题记录下来,使用的环境是VS2017,网上的资料普遍太老了 需要注意,如果使用多项目同时启动的方式需要把WCF调整到WF启动顺序之上 1.怎么使用代码活动 新建 ...
- Day 4-1 模块的导入方法和路径
什么是模块? 在计算机程序的开发过程中,随着程序代码越写越多,在一个文件里代码就会越来越长,越来越不容易维护. 为了编写可维护的代码,我们把很多函数分组,分别放到不同的文件里,这样,每个文件包含的代码 ...
- 机顶盒webview开发调试
安装node的anywhere插件 启动本地服务器后 使用chrome的DevTool-----> chrome://inspect/#devices 点击inspect 第一次需要FQ ...
- springboot 如何操作redis
1.首先应该引入 依赖 <dependency> <groupId>org.springframework.boot</groupId> <artifactI ...
- pring @Configuration 和 @Component 区别
一句话概括就是 @Configuration 中所有带 @Bean 注解的方法都会被动态代理,因此调用该方法返回的都是同一个实例. 从定义来看, @Configuration 注解本质上还是 @Com ...
- Hbase数据表解析
demo为表的命名空间,user为表的名字you2个列族,一个为b.一个为o. NAME 为列族名,Replication_SCOPE实现一个远程集群的复制.compression数据压缩的类型 Hb ...
- linux安装php7.2.7
1.下载php 官网下载:#wget http://cn2.php.net/get/php-7.2.7.tar.gz/from/a/mirror.(ps:应该是这么下载的,但是我下载的都是一个mirr ...