当前位置: 首页 > news >正文

ABC 368 G - Add and Multiply Queries

原题链接:G - Add and Multiply Queries

题意:给出数组a和b,三种操作,第一种:以 1 i x 的形式给出。用x替换ai​。第二种:以 2 i x 的形式给出。用x代替 bi​ 。第三种:以3 l r的形式给出,初始值为0,从l到r每个位置上可以选择加上a[i],或者乘上b[i],输出最大值。

思路:链表+set+树状数组+二分。题目中给出了答案的范围不会超过1e18,那么就可以知道每次第三种操作的区间里面b数组大于等于2的数的数量不会大于63个。

因为初始值是0,所以第一次操纵一定是选择a[l],从l+1开始到b数组里面第一次出现大于等于2的数之间,肯定是之间加上a数组里面的数更加优秀,那么这一段区间的和怎么维护呢?因为操作一会修改a数组,所以需要可以满足区间查询,单点修改的数据结构,那么就是树状数组。这样操作一就完成。

考虑如何快速的找到b数组里面大于等于2的数的位置?可以使用链表来维护,链表的含义是当前位置的b数组值大于等于2的下一个大于等于2的位置,这样的话,就可以先找到[l,r]区间里面第一个大于等于2的位置,然后不断的往后面跳跃,直到大于r。那么怎么快速的找到第一个位置呢?可以想打把每一个节点的位置塞到set里面,然后二分的查找就可以了。这样操作三就完成了。

对于操作二来说,因为是用链表来写的,所以如果改变的值大于等于2,那么就把改变的位置加入链表,如果小于2,并且b数组这个位置大于2,那么就把这个节点舍弃。如何快速的找当前点之前的呢,还是在set里面二分。

//冷静,冷静,冷静
//调不出来就重构
//#pragma GCC optimize(2)
//#pragma GCC optimize("O3")
#include<bits/stdc++.h>
#define endl '\n'
using namespace std;
typedef long long ll;
typedef long double ld;
typedef pair<ll,ll> pii;
const int N=1e6+10,mod=1000000007;
ll a[N],b[N],r[N],tree[N],l[N]; 
ll lowbit(ll x)
{return x&(-x);
}
ll query(ll x)
{ll sum=0;while(x){sum+=tree[x];x-=lowbit(x);}return sum;
}
void updata(ll x,ll n,ll vel)
{while(x<=n){tree[x]+=vel;x+=lowbit(x);}
}
void Jiuyuan()
{ll n;cin>>n;for(int i=1;i<=n;i++)//读入a,并且更新树状数组 {cin>>a[i];updata(i,n,a[i]);}for(int i=1;i<=n;i++)cin>>b[i];ll id=n+1;set<ll> op;for(int i=n;i;i--)//建立双向链表 {if(b[i]>=2){r[i]=id;l[id]=i;op.insert(id);id=i;}}r[0]=id;l[id]=0;op.insert(id);ll q;cin>>q;while(q--){ll nm;cin>>nm;if(nm==1){ll wz,x;cin>>wz>>x;updata(wz,n,-a[wz]+x);a[wz]=x;}else if(nm==2){ll wz,x;cin>>wz>>x;ll hj=*op.lower_bound(wz);//先找到大于等于x的位置,然后这个位置之前的一个,那么wz就会被夹在中间 hj=l[hj];if(x>=2){ll a=hj,b=wz,c=r[hj];if(c==wz)c=r[c];//如果本身就是大于等于2,那么就需要在多跳一次 r[a]=b;l[b]=a;r[b]=c;l[c]=b;op.insert(wz);}else{if(b[wz]>=2){ll a=hj,b=wz,c=r[hj];if(c==wz)c=r[c];r[a]=c;l[c]=a;op.erase(wz);}}b[wz]=x;}else{ll x,y;cin>>x>>y;ll cs=a[x];x++;ll hj=*op.lower_bound(x);//找到第一个大于等于x并且满足要求的位置 while(hj<=y){ll xx=x,yy=hj-1;if(yy>=xx)//如果中间有b数组为1的区间,那么就加上a数组的值 {cs+=query(yy);cs-=query(xx-1);}cs=max(cs+a[hj],cs*b[hj]);//1*6 1+6 明显后者更好,所以比较一下 x=hj+1;hj=r[hj];}cs+=query(y);//如果有多余的,那么就加上a数组的值 cs-=query(x-1);cout<<cs<<endl;}}
}
int main()
{ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);ll T=1;
//	cin>>T;while(T--){Jiuyuan();}return 0;
} 

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • [Day 63] 區塊鏈與人工智能的聯動應用:理論、技術與實踐
  • PyTorch踩坑记录1
  • SQLserver中的DATEADD使用、avg使用、Round使用
  • iOS profiles文件过期如何更新
  • Linux环境下使用Git把代码上传到云端
  • Codeforces Round 968 (Div. 2 ABCD1D2题) 视频讲解
  • 【计算机组成原理】汇总三、存储系统
  • 机械学习—零基础学习日志(如何理解概率论4)
  • 京准同步:北斗授时设备(北斗校时服务器)操作指南
  • MVVM分层思想
  • 图形学论文笔记
  • Qt WebSocket
  • 10款主流图纸加密软件大盘点(为图纸穿上隐形衣)
  • 幅频特性曲线分析及使用WPF绘制
  • 动手学深度学习7.7. 稠密连接网络(DenseNet)-笔记练习(PyTorch)
  • ----------
  • [笔记] php常见简单功能及函数
  • 【跃迁之路】【733天】程序员高效学习方法论探索系列(实验阶段490-2019.2.23)...
  • Android交互
  • C++类的相互关联
  • CentOS从零开始部署Nodejs项目
  • gf框架之分页模块(五) - 自定义分页
  • iOS 系统授权开发
  • java8-模拟hadoop
  • log4j2输出到kafka
  • Spring核心 Bean的高级装配
  • Travix是如何部署应用程序到Kubernetes上的
  • 快速体验 Sentinel 集群限流功能,只需简单几步
  • 浅谈Kotlin实战篇之自定义View图片圆角简单应用(一)
  • 巧用 TypeScript (一)
  • 最近的计划
  • 看到一个关于网页设计的文章分享过来!大家看看!
  • ​sqlite3 --- SQLite 数据库 DB-API 2.0 接口模块​
  • ​数据结构之初始二叉树(3)
  • #{}和${}的区别是什么 -- java面试
  • %check_box% in rails :coditions={:has_many , :through}
  • (31)对象的克隆
  • (AngularJS)Angular 控制器之间通信初探
  • (LeetCode C++)盛最多水的容器
  • (Note)C++中的继承方式
  • (八十八)VFL语言初步 - 实现布局
  • (二)Linux——Linux常用指令
  • (九)One-Wire总线-DS18B20
  • (原創) 如何將struct塞進vector? (C/C++) (STL)
  • (转)c++ std::pair 与 std::make
  • (转)Google的Objective-C编码规范
  • (转载)从 Java 代码到 Java 堆
  • *Algs4-1.5.25随机网格的倍率测试-(未读懂题)
  • .NET / MSBuild 扩展编译时什么时候用 BeforeTargets / AfterTargets 什么时候用 DependsOnTargets?
  • .NET 5.0正式发布,有什么功能特性(翻译)
  • .NET C# 操作Neo4j图数据库
  • .NET MVC、 WebAPI、 WebService【ws】、NVVM、WCF、Remoting
  • .NET 的静态构造函数是否线程安全?答案是肯定的!
  • .NET 中让 Task 支持带超时的异步等待
  • .net 逐行读取大文本文件_如何使用 Java 灵活读取 Excel 内容 ?