The Preliminary Contest for ICPC China Nanchang National Invitational I. Max answer(单调栈 + rmq)

博客围绕一个算法问题展开,给定序列,每个区间贡献值为区间最小值乘区间和,求最大贡献值。介绍用单调栈找到每个数作为最小值影响的最大区间,还给出不同情况下计算区间最值的方法,如根据数的正负及前缀和计算,最后给出案例说明。

题目:

  •  11.46%
  •  3000ms
  •  262144K

Alice has a magic array. She suggests that the value of a interval is equal to the sum of the values in the interval, multiplied by the smallest value in the interval.

Now she is planning to find the max value of the intervals in her array. Can you help her?

Input

First line contains an integer n(1 \le n \le 5 \times 10 ^5n(1≤n≤5×105).

Second line contains nn integers represent the array a (-10^5 \le a_i \le 10^5)a(−105≤ai​≤105).

Output

One line contains an integer represent the answer of the array.

样例输入复制

5
1 2 3 4 5

样例输出复制

36

题意:给你一个序列,每一个区间有一个贡献值,等于这个区间中的最小值 × 这段区间和,求贡献值的最大值。

单调栈:可以找到左边或者右边第一个大于/小于自己的数。时间复杂度为O(N);

思路:枚举每个数作为最小值,这个数作为最小值影响的最大的区间,可以用单调栈求出。

不会的请看视频:https://www.bilibili.com/video/av23189029?from=search&seid=18026655336668737255

当求出每个数作为最小值影响的区间时

当这个数a[i]>=0时,a[i] 为正数,a[i]还是最小,所以 当前最为最小值区间的贡献值为a[i] * 影响区间的区间和;

当a[i] < 0 时,在a[i]作为最小值影响区间中,包含a[i]的区间的最小值。但是要怎么求这个区间的最小值呢,

首先我们先求出所有数的前缀和,假设以a[i]为最小值影响的区间的左、右端点分别为l,r,先求出 l~i 下标的前缀和的最大值 k1,再求出i~r下标的前缀和的最小值 k2,k2 - k1就是所要找的区间的最小值。这里需要注意,k1为负数时,要减去max(k1,sum[l-1]),求最值的话用 rmq维护前缀和就行

结论1:在一段区间[1,n] 中求包含这个数的区间的最小值:先求出所有数前缀和,再求出 1~i 下标的前缀和的最大值 k1,再求出i~n下标的前缀和的最小值 k2,k2 - k1就是所要找的包含这个数区间的最小值。

结论2:在一段区间[1,n]中求包含这个数的区间和最大值,预处理所有数的前缀和,再求出1~i下标的前缀和的最小值k1 和 i~n下标的最大值k2,k2 - k1 就是所有要找的包含这个数的区间的最大值。
案例1

-11  2  3   -5   -4

-11 -9  -6  -11 -15           看-5,-15 - max(-11,-6) = -9. (-5) *(-9) = 40.

案例2:

4  -5   -2   1   -2  -3   -2   -1  4

4   -1  -3  -2  -4   -7   -9  -10 -6           看a[i] = -3时的状态 

 

代码:

#include<bits/stdc++.h>
using namespace std;
const int Max = 5e5;
#define ll long long
struct node
{
	int val,id;
	int l,r;
}stu[Max+10];
stack<node> s;
int n,Log[Max+10],c[30];
ll sum[Max+10],dpM[Max+10][21],dpN[Max+10][21];
void D_R()    // 单调栈,求右边第一个小于它的数;	 
{
	for(int i = 1;i<=n;i++)
	{
		stu[i].r = n+1;
		while(s.size()&&s.top().val>stu[i].val)
		{
			node tt = s.top();
			s.pop();
			stu[tt.id].r = i;
		}
		s.push(stu[i]);
	}
	while(s.size())
		s.pop();
}
void D_L()
{
	for(int i = n;i>=1;i--)
	{
		stu[i].l = 0;
		while(s.size()&&s.top().val>stu[i].val)
		{
			node tt = s.top();
			s.pop();
			stu[tt.id].l = i;
		}
		s.push(stu[i]);
	}
	while(s.size())
		s.pop();
}
void rqm()
{
	for(int j = 1;j<=Log[n];j++)
		for(int i = 1;i+c[j]-1<=n;i++){
			dpM[i][j] = max(dpM[i][j-1],dpM[i+c[j-1]][j-1]);
			dpN[i][j] = min(dpN[i][j-1],dpN[i+c[j-1]][j-1]); 
		}
	
}
int main()
{	
   c[0] = 1;
	for(int i = 1;i<=21;i++)
		c[i] = c[i-1] * 2;
	scanf("%d",&n);
	Log[0] = -1;
	for(int i = 1;i<=n;i++){
		scanf("%d",&stu[i].val);
		Log[i] = Log[i>>1] + 1;
		stu[i].id = i;
		sum[i] = sum[i-1] + (ll)stu[i].val; 
		dpM[i][0] = dpN[i][0] = sum[i];
	}
	rqm();
	D_R();	
	D_L();
	ll ans = -0x3f3f3f3f3f3f3f;
	for(int i = 1;i<=n;i++){
		if(stu[i].val>=0) 
			ans = max((ll)stu[i].val*(sum[stu[i].r-1]-sum[stu[i].l]),ans);
		else{
			
			int l = stu[i].l+1,r = stu[i].r - 1;
			int t1 = Log[i-l+1],t2 = Log[r-i+1];
			ll k1 = max(dpM[l][t1],dpM[i-c[t1]][t1]);
			ll k2 = min(dpN[i][t2],dpN[r-c[t2]][t2]);
			if(k1>=0) ans = max(ans,(ll)stu[i].val * (k2-k1));
			else  ans = max(ans,(ll)stu[i].val*(k2-max(sum[stu[i].l],k1)));
				// 减去 max(边界值,k1)两者的较大值。 
		}
	}
	printf("%lld\n",ans);
	return 0;	
}

 

<think>我们正在处理一个关于FDTD Solutions软件中文件无法打开的问题。用户报告的错误是:"FDTD file pid_grating_coupler_preliminary_design.fsp not found or could not be opened"。这个错误通常意味着软件无法在指定路径找到该文件,或者文件存在但已损坏,或者没有足够的权限访问。 根据引用内容[^1],用户之前可能运行了一个Python脚本(pid_grating_coupler_sweep_2D.py),该脚本试图打开这个FSP文件。因此,问题可能出现在脚本中指定的文件路径不正确,或者文件被移动、删除,或者权限问题。 解决步骤: 1. **检查文件路径**: - 确保文件`pid_grating_coupler_preliminary_design.fsp`确实存在于脚本所期望的路径中。 - 在脚本中,检查打开文件时使用的路径是绝对路径还是相对路径。如果是相对路径,确保当前工作目录正确。 2. **检查文件权限**: - 确认用户有读取该文件的权限。在Windows上,可以右键点击文件,选择“属性”->“安全”选项卡查看权限。在Linux/macOS上,使用`ls -l`命令查看权限。 3. **检查文件是否损坏**: - 尝试手动打开该FSP文件(通过FDTD Solutions的图形界面)。如果图形界面也无法打开,则文件可能已损坏。 - 如果文件损坏,尝试从备份中恢复。 4. **检查脚本代码**: - 打开脚本`pid_grating_coupler_sweep_2D.py`,检查打开文件的部分。例如,在FDTD Solutions的脚本环境中,打开文件的命令可能是`load`或`open`。确保路径字符串正确,并且使用了正确的转义(在Windows中使用双反斜杠`\\`或正斜杠`/`)。 5. **其他可能性**: - 如果文件路径包含非英文字符,可能会引起问题,尝试将路径改为全英文字符。 - 检查文件是否被其他程序占用(如另一个FDTD Solutions实例)。 如果用户是在运行脚本时遇到此错误,那么修改脚本中的文件路径可能是最直接的解决方法。如果文件丢失,则需要重新创建或从备份中恢复。 下面,我们将生成相关问题,以帮助用户进一步排查或提供更多信息。</think>### FDTD文件无法打开的解决方案 当遇到"FDTD file pid_grating_coupler_preliminary_design.fsp not found or could not be opened"错误时,请按以下步骤排查: 1. **文件路径检查** - 确认文件是否存在于指定目录 - 检查路径中是否包含特殊字符或空格(建议使用纯英文路径) - 尝试使用绝对路径而非相对路径 - 验证脚本中的路径分隔符(Windows使用`\`或`/`,Linux/macOS使用`/`) 2. **文件权限验证** - 检查用户账户是否有文件读取权限 - 右键文件 > 属性 > 安全选项卡,确认当前用户有"读取"权限 - 尝试将文件复制到用户文档目录再打开 3. **文件完整性检查** - 确认文件大小是否正常(异常小的文件可能已损坏) - 尝试在其他FDTD Solutions实例中打开 - 检查备份版本是否能正常打开 4. **软件环境确认** - 确保FDTD Solutions版本与创建文件的版本兼容 - 检查Python脚本中加载文件的命令是否正确: ```python # 示例代码 - 检查脚本中的加载命令 import lumapi fdtd = lumapi.FDTD() fdtd.load("pid_grating_coupler_preliminary_design.fsp") # 确认路径正确 ``` - 重启FDTD Solutions软件和计算机 5. **脚本调试建议** - 在脚本开头添加路径打印: ```python import os print("当前工作目录:", os.getcwd()) print("文件路径:", os.path.abspath("pid_grating_coupler_preliminary_design.fsp")) ``` - 使用`try-except`捕获错误详情: ```python try: fdtd.load("pid_grating_coupler_preliminary_design.fsp") except Exception as e: print("加载失败:", str(e)) ``` 如果以上步骤仍无法解决,可能是文件损坏,建议从版本控制系统或备份中恢复文件[^1]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值