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

LG10516

虽然本题打着线段树的标签,但 \(10^5\) 的数据范围令我想到了简单粗暴的分块。

  • 操作 \(1\)

首先考虑暴力判断并修改每个位置的值,然而这样做会被卡到 \(O(nm)\)。但实际上,需要修改的位置可能不多,也就是会做大量的无用判断。这个时候,我们就可以充分利用分块的特性,记录每个块内 \(a_i \times b_i\) 的最小值,若该最小值比 \(k\) 大,则整个块都无需修改,直接跳过,否则暴力修改,并更新该块的信息。这样做效率得到了极大的提升,\(O(nm)\) 很难跑满。

注意,\(t=0\) 时并不会产生任何操作效果,因此直接忽略即可,运行效率可获得部分的提升。

  • 操作 \(2\)

分块的基础操作。直接定位所在的块,暴力修改并更新该块的信息。单次操作时间复杂度为 \(O(\sqrt n)\)

  • 操作 \(3\)

也是分块的基础操作。利用先前已经维护好的信息,直接求和即可。单次操作时间复杂度为 \(O(\sqrt n)\)

完整代码如下:

#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#define N 200001
#define int long longusing namespace std;int n,a[N],b[N],tot,x[N],y[N],mi[N],s[N],id[N],ans,len,l,r,k,t,op,lt,rt;inline int read()
{int x=0,f=1;char ch=getchar();while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}while (ch>='0'&&ch<='9'){x=x*10+ch-48;ch=getchar();}return x*f;
}signed main()
{int T;cin >> n >> T;for( int i = 1 ; i <= n ; i ++ )a[i] = read();for( int i = 1 ; i <= n ; i ++ )b[i] = read();len = sqrt( n );l = 1;while( l <= n ){r = min( l + len - 1 , n );tot ++;x[tot] = l,y[tot] = r;mi[tot] = a[l] * b[l];id[l] = tot;s[tot] = a[l] + b[l];for( int i = l + 1 ; i <= r ; i ++ )mi[tot] = min( mi[tot] , a[i] * b[i] ),id[i] = tot,s[tot] += a[i] + b[i];l = r + 1;}while( T -- ){op = read();if( op == 1 ){l = read(),r = read(),k = read(),t = read();if( t == 0 ) continue;lt = id[l];rt = id[r];for( int i = lt ; i <= rt ; i ++ ){if( mi[i] > k ) continue; for( int j = max( x[i] , l ) ; j <= min( y[i] , r ) ; j ++ ){if( a[j] * b[j] <= k ){a[j] += t;b[j] += t;s[i] += t * 2;}}mi[i] = a[x[i]] * b[x[i]];for( int j = x[i] + 1 ; j <= y[i] ; j ++ )mi[i] = min( mi[i] , a[j] * b[j] );}}if( op == 2 ){k = read(),l = read(),r = read();s[id[k]] = s[id[k]] - a[k] + l - b[k] + r;;a[k] = l,b[k] = r;mi[id[k]] = a[x[id[k]]] * b[x[id[k]]];for( int i = x[id[k]] + 1 ; i <= y[id[k]] ; i ++ )mi[id[k]] = min( mi[id[k]] , a[i] * b[i] );}if( op == 3 ){l = read(),r = read();lt = id[l];rt = id[r];ans = 0;for( int i = lt ; i <= rt ; i ++ ){if( l <= x[i] && y[i] <= r ){ans += s[i];continue;}for( int j = max( x[i] , l ) ; j <= min( y[i] , r ) ; j ++ )ans += a[j] + b[j];}printf( "%lld\n" , ans );}}return 0;
}
http://www.agseo.cn/news/257/

相关文章:

  • 11.1 定义类和对象
  • C#.NET EFCore.BulkExtensions 扩展详解
  • 2025AI赋能HR新纪元,中国AI HR主流厂商大盘点
  • Linux作业及状态转换
  • C++小白修仙记_LeetCode刷题_队列
  • 设备驱动程序和设备独立性软件的区别
  • Fastjson 1.2.47 远程代码执行
  • 树状数组板子
  • 私有化部署Dify构建企业AI平台教程
  • 树状数组板子2
  • 网络流——OI复健
  • 2025“钉耙编程”中国大学生算法设计暑期联赛(3)
  • Symfony学习笔记 - Symfony Documentation - Getting Started(下)
  • MySQL事务
  • 线段树板子
  • 双列圆锥滚子轴承载荷分布计算程序
  • NOIP 集训日记
  • 矢量篇 - KMLKMZ转SHP
  • js空值合并运算符?? - jerry
  • 记录---让网页像现实世界一样“拿起来,放进去”
  • Python面向对象
  • ubuntu上通过kvm新建虚拟机
  • buntu22.04 LTS安装docker以及docker-compose实践
  • 关于USB 无线 WIF 设备驱动安装的问题
  • Spring Boot常用注解-详细解析+示例 - 指南
  • test
  • Ubuntu22.04安装Docker过程记录
  • linux
  • 20分钟快速入门Docker
  • K8S的基础概念