首页 > 其他分享 >P11217 【MX-S4-T1】「yyOI R2」youyou 的垃圾桶(线段树上二分)

P11217 【MX-S4-T1】「yyOI R2」youyou 的垃圾桶(线段树上二分)

时间:2024-10-21 08:51:43浏览次数:1  
标签:R2 yyOI int sum mid tot T1 query LL

link

赛时是想到普通的线段树 + 二分 \(O(q\log^2n)\),预期是 70pts,实际 50pts

后面发现又是在 long long 类型的计算中,1ll 写成了 1,然后爆负数,复杂度就错了,T 了四个点


开题,读起来是一个很套路的题目

要对区间在线修改,区间加、(区间乘?),发现数据很大,那就是线段树、树状数组维护了

思考了一下,答案可以分两部分求解,

一是找到使 youyou 死亡的那一轮,之前轮的贡献可以按题意累加得到,

	LL sum = query(1, 1, n), tot = 0ll, last;
	int cnt = 0ll; // 实际到第 cnt 轮就死亡 
	while (tot < W)
	{
		last = tot;
		tot = sum * (LL)(1ll << cnt) + last;
		cnt ++;
	}
	ans += (LL)((cnt - 1ll) * n); // 所有点覆盖轮 
	W -= last;

手算了一下时间复杂度应该是 \(O(x)\) 满足 \(sum\sum\limits_{i = 0}^x 2^i = W\),等比数列求和一下近似 \(O(\log n)\)

我一开始测大样例 2s 内本地跑不出来,以为是写假了(就是写假了 qwq,爆负数),然后卡了好久在那想怎么做到 \(sum\cdot 2^x=W\),白给了很多时间

这里推导一下等比数列求和 qwq
\(S_x = sum\sum\limits_{i=0}^x 2^i\)
\(2S_x = sum\sum\limits_{i=1}^{x + 1} 2^i\)
\(S_x = 2S_x - S_x = sum\cdot 2^{x+1} - sum\cdot 2^0 = W\)
\(x = \log_2(\frac{W}{2sum} + \frac{1}{2})\)

二是确定为第 i 轮死亡时,想到从左往右覆盖具有单调性,可以把死亡位置二分出来,每次求个前缀和

时间复杂度是 \(O(\log^2n)\) 的

需要注意的是,我一开始是考虑第 i 轮要用区间乘实现,后来发现还要还原,有点不可做的感觉

但是再仔细一想,注意到第 i 轮的初始值是整体偏移的,且并不关心单个数值偏移后的具体大小,那我直接求出第一轮的和然后乘上对应的偏移量就可以了

可以拿到 70pts

code
#include <bits/stdc++.h>
#define re register int 
#define lp p << 1
#define rp p << 1 | 1
#define int long long

using namespace std;
typedef long long LL;
const int N = 2e5 + 10;
const LL inf = 1e18;

int n, T, a[N];
LL W0, ans;
struct Tree
{
	int l, r, tag;
	LL sum;
}t[N << 2];

inline void push_up(int p)
{
	t[p].sum = t[lp].sum + t[rp].sum;	
} 

inline void push_down(int p)
{
	if (t[p].tag)
	{
		t[lp].sum += (LL)(t[lp].r - t[lp].l + 1) * (LL)t[p].tag;
		t[rp].sum += (LL)(t[rp].r - t[rp].l + 1) * (LL)t[p].tag;
		t[lp].tag += t[p].tag;
		t[rp].tag += t[p].tag;
		t[p].tag = 0;
	}
}

inline void build(int p, int l, int r)
{
	t[p].l = l, t[p].r = r;
	if (l == r)
	{
		t[p].sum = a[l];
		return;
	}
	int mid = (l + r) >> 1;
	build(lp, l, mid);
	build(rp, mid + 1, r);
	push_up(p);
}

inline void update(int p, int l, int r, int k)
{
	if (l <= t[p].l && t[p].r <= r)
	{
		t[p].sum += (LL)(t[p].r - t[p].l + 1) * k;
		t[p].tag += k;
		return;
	}
	push_down(p);
	int mid = (t[p].l + t[p].r) >> 1;
	if (l <= mid) update(lp, l, r, k);
	if (r > mid) update(rp, l, r, k);
	push_up(p);	
}

inline LL query(int p, int l, int r)
{
	if (l <= t[p].l && t[p].r <= r) return t[p].sum;
	push_down(p);
	LL res = 0ll;
	int mid = (t[p].l + t[p].r) >> 1;
	if (l <= mid) res += query(lp, l, r);
	if (r > mid) res += query(rp, l, r);
	
	return res;
}

signed main()
{
	ios::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);
	
//	freopen("wxyt3.in", "r", stdin);
//	freopen("wxyt3.out", "w", stdout);
	
	cin >> n >> T >> W0;
	for (re i = 1; i <= n; i ++) cin >> a[i];
	build(1, 1, n);
	while (T --)
	{
		ans = 0ll; 
		LL W = W0;
		
		int L, R, d; cin >> L >> R >> d;
		update(1, L, R, d);
		
		LL sum = query(1, 1, n), tot = 0ll, last;
		int cnt = 0ll; // 实际到第 cnt 轮就死亡 
		while (tot < W)
		{
			last = tot;
			tot = sum * (LL)(1ll << cnt) + last;
			cnt ++;
		}
		ans += (LL)((cnt - 1ll) * n); // 所有点覆盖轮 
		W -= last;
		
		int l = 1, r = n;
		while (l < r)
		{
			int mid = (l + r) >> 1;
			if (W - query(1, 1, mid) * (LL)(1ll << (cnt - 1ll)) <= 0) r = mid;
			else l = mid + 1;
		}
		ans += (LL)(l - 1ll);
		cout << ans << '\n';
	}
	return 0;
}

瓶颈就是它卡两只 log,,,再考虑到线段树本身常数较大(可能树状数组可以冲一下?

可能有其他做法,std 是 \(O(n\log W + q)\) 的,没去看

消去一只 log 的办法就是在线段树上直接二分,找左右子树,很妙的办法

ac code
#include <bits/stdc++.h>
#define re register int
#define lp p << 1
#define rp p << 1 | 1
#define int long long

using namespace std;
typedef long long LL;
const int N = 2e5 + 10;
const LL inf = 1e18;

int n, T, a[N];
LL W0, ans;
struct Tree
{
	int l, r, tag;
	LL sum;
}t[N << 2];

inline void push_up(int p)
{
	t[p].sum = t[lp].sum + t[rp].sum;
} 

inline void push_down(int p)
{
	if (t[p].tag)
	{
		t[lp].sum += (LL)(t[lp].r - t[lp].l + 1) * (LL)t[p].tag;
		t[rp].sum += (LL)(t[rp].r - t[rp].l + 1) * (LL)t[p].tag;
		t[lp].tag += t[p].tag;
		t[rp].tag += t[p].tag;
		t[p].tag = 0;
	}
}

inline void build(int p, int l, int r)
{
	t[p].l = l, t[p].r = r;
	if (l == r)
	{
		t[p].sum = a[l];
		return;
	}
	int mid = (l + r) >> 1;
	build(lp, l, mid);
	build(rp, mid + 1, r);
	push_up(p);
}

inline void update(int p, int l, int r, int k)
{
	if (l <= t[p].l && t[p].r <= r)
	{
		t[p].sum += (LL)(t[p].r - t[p].l + 1) * k;
		t[p].tag += k;
		return;
	}
	push_down(p);
	int mid = (t[p].l + t[p].r) >> 1;
	if (l <= mid) update(lp, l, r, k);
	if (r > mid) update(rp, l, r, k);
	push_up(p);	
}

inline LL query(int p, int l, int r)
{
	if (l <= t[p].l && t[p].r <= r) return t[p].sum;
	push_down(p);
	LL res = 0ll;
	int mid = (t[p].l + t[p].r) >> 1;
	if (l <= mid) res += query(lp, l, r);
	if (r > mid) res += query(rp, l, r);
	
	return res;
}

inline int query2(int p, int l, int r, LL W, LL layer)
{
	if (l == r) return l;
	push_down(p);
	int mid = (l + r) >> 1;
	if (W - t[lp].sum * layer <= 0) return query2(lp, l, mid, W, layer);
	else return query2(rp, mid + 1, r, W - t[lp].sum * layer, layer); 
}

signed main()
{
	ios::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);
	
//	freopen("wxyt3.in", "r", stdin);
//	freopen("wxyt3.out", "w", stdout);
	
	cin >> n >> T >> W0;
	for (re i = 1; i <= n; i ++) cin >> a[i];
	build(1, 1, n);
	while (T --)
	{
		ans = 0ll; 
		LL W = W0;
		
		int L, R, d; cin >> L >> R >> d;
		update(1, L, R, d);
		
		LL sum = query(1, 1, n), tot = 0ll, last;
		int cnt = 0ll; // 实际到第 cnt 轮就死亡 
		while (tot < W)
		{
			last = tot;
			tot = sum * (LL)(1ll << cnt) + last;
			cnt ++;
		}
		ans += (LL)((cnt - 1ll) * n); // 所有点覆盖轮 
		W -= last;
		
		int pos = query2(1, 1, n, W, (LL)(1ll << (cnt - 1ll))) - 1;
		cout << ans + pos << '\n';
	}
	return 0;
}

标签:R2,yyOI,int,sum,mid,tot,T1,query,LL
From: https://www.cnblogs.com/wenzieee/p/18488072

相关文章

  • (环境篇日志-CVPR2024 ) Physical 3D Adversarial Attacks against Monocular Depth E
    题目:Physical3DAdversarialAttacksagainstMonocularDepthEstimationinAutonomousDriving作者:JunhaoZheng,ChenhaoLin*,JiahaoSun,ZhengyuZhao,QianLi,ChaoShen*单位:Xi’anJiaotongUniversity收录:CVPR2024论文:[Physical3DAdversarialAttacks......
  • jsp高等学校体育场馆设施管理系统6r24x
    jsp高等学校体育场馆设施管理系统6r24x本系统(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。系统程序文件列表项目功能教师,体育场馆,运动器材,教学计划,场馆预约,器材借用,器材归还,预约取消技术要求:   开发语言:JSP前端使......
  • 初探AI之got-ocr2.0大模型本地部署与遇到的各种坑处理
    一、环境搭建1.安装cuda,本人使用的是12.1版本,下载地址:https://developer.nvidia.com/cuda-12-1-1-download-archive2.安装conda3,https://blog.csdn.net/m0_73634846/article/details/1363783503.准备代码环境原文:https://mp.weixin.qq.com/s/PQVrlr5FoVb89Mivzi7pLA顺序执......
  • DK5V120R15ST1东科高效率同步整流芯片
    产品概述DK5V120R15ST1是一款简单高效率的同步整流芯片,只有A,K两个功能引脚,分别对应肖特基二极管PN管脚。芯片内部集成了120V功率NMOS管,可以大幅降低二极管导通损耗,提高整机效率,取代或替换目前市场上等规的肖特基整流二极管。DK5V120R15ST1采用TO-220F封装。主要特点......
  • Tomcat10JdbcPoolDemo
    packagecom.renguanyu.demo;importjava.sql.Connection;importjava.sql.ResultSet;importjava.sql.Statement;importorg.apache.tomcat.jdbc.pool.DataSource;importorg.apache.tomcat.jdbc.pool.PoolProperties;publicclassTomcat10JdbcPoolDemo{ public......
  • 【React】React17+配置Babel实现无需导入React就可以使用jsx
    React17以后,无需引入React包,就可以使用jsx语法,官网说明。Babel版本首先Babel要使用V7.9.0以上如果使用的是@babel/plugin-transform-react-jsxnpmupdate@babel/core@babel/plugin-transform-react-jsx如果使用的是@babel/preset-reactnpmupdate@babel/cor......
  • Adobe Premiere(简称PR2024)视频编辑软件下载
    一、发展历史1.1早期版本AdobePremiere(简称PR)是Adobe公司推出的一款视频编辑软件,其历史可以追溯到1991年。当时,Adobe发布了Premiere1.0版本,仅支持MacOS系统。1993年9月,Adobe公司推出了首个针对Windows系统的Premiere版本,这使得更多用户能够接触和使用这款强大的视频编辑工......
  • CitrixWindows SQL Server2016安装教程 SQL管理工具SSMS安装
    CitrixWindowsSQLServer2016安装教程SQL管理工具SSMS安装   ......
  • 抽象作者被 T1 打爆
    考了一道抽象AGC,属实是逆天了。description令\(M\)为一正整数。给出\(2N\)个整数\(a_1,a_2,\ldots,a_{2N}\),满足\(0\lea_i<M\)。你需要把这\(2N\)个整数分成\(N\)对,每一对\((x,y)\)的权值为\((x+y)\bmodM\)。令一种分配方案的权值为每一对的权......
  • 《天空之山》提示找不到xinput1_3.dll怎么办,xinput1_3.dll缺失的解决之道
    针对《天空之山》提示找不到xinput1_3.dll的问题,以下是一些有效的解决之道:一、了解xinput1_3.dll文件的重要性xinput1_3.dll是DirectX组件中的一个重要文件,它提供对Xbox360控制器和其他兼容设备的原生支持。对于许多游戏,包括《天空之山》,这个文件是必需的,以确保游戏能够正......