首页 > 其他分享 >AT_arc067_f 题解

AT_arc067_f 题解

时间:2023-06-29 21:11:16浏览次数:44  
标签:le int 题解 sum 差分 arc067 buf 单调

传送门

Simplify

不难想到其实题意就是让你求:

\[\max_{1\le l\le r\le n}\left\{\sum_{i=1}^m\max_{l\le j\le r}\{b_{i,j}\}-\sum_{i=l}^ra_i\right\} \]

Solution

首先考虑暴力,我的话是枚举 \(l,r(l\in[1,n],l\in[1,r])\),然后 \(m\) 个单调队列先把 \(l\) 到 \(r\) 的 b 数组存进去,然后从 \(1\) 到 \(r\) 依次将超出范围的队头弹出维护最大值,\(\sum_{i=l}^ra_i\) 就直接前缀和。

时间复杂度为 \(O(n^2m)\),显然会炸,于是考虑优化。

枚举过程中保持单调不变的是 \(r\),而 \(l\) 会重复遍历……有重复的部分?

那么我们可以每次入完队后存一下这次的历史版本,以便在 \(r+1\) 的时候可以免去“\(m\) 个单调队列先把 \(l\) 到 \(r\) 的 b 数组存进去”这个操作。

但是任然解决不了问题。

想要将复杂度降下来,我们是不是可以考虑优化掉那个 \(O(n)\) 的枚举 \(l\),想想怎么才能把它优化掉……

简单,就是把每个 \(1\le j\le m\) 的 \(\max_{l\le i\le r}\{b_{i,j}\}\) 预处理出来,这样复杂度就降为 \(O(n^2+nm)\),但是,怎么预处理呢?

再思考思考,我们会发现一些性质(废话),就是在枚举 \(l\) 时单调队列的队头的 \(b\) 值是成单调递减的,且第 \(k\) 个队头 \(l_k\) 是会从 \(l_{k-1} + 1\) 保持到 \(l_k\) 的,再通俗一点,在 \(l\) 的遍历过程中,会有一段的最大值是不变的,再再再通俗一点,就是再一段区间里的最大值相等。

诶?差分!我们在 \(l_k\) 和 \(l_{k-1}\) 上进行差分,大概长这个样子:

这样就好做多了,但是一个新的 \(r\) 入队时有可能会让这张图顶上的即队尾的几个 \(l\) 弹出,那我们用丹钓战维护啊(况且这图也像个丹钓战),在弹出过程中更改一下当前队尾的差分数组(减去 \(b_{l_k,j}-b_{l_{k+1},j}\)(本来是设为 \(0\),但是维护的是整个 \(m\) 行的差分,所以不能设为 \(0\))),出队出完了之后了的队尾要加上 \(b_{l_{p+1},j}-b_{r,j}\)(不是变为 \(b_{l_p,j}-b_{r,j}\) 的原因与上面的同理)。单调队列什么的丢掉。

我们需要预处理的 \(\max_{l\le i\le r}\{b_{i,j}\}\) 即为这个差分数组的前缀和。

这不就做完了吗。

顺便最优解。

Code

#include<bits/stdc++.h>
using namespace std;
 
typedef long long ll;
const int N = 5005, M = 205;
 
inline char nc(){ static char buf[1000000],*p=buf,*q=buf; return p==q&&(q=(p=buf)+fread(buf,1,1000000,stdin),p==q)?EOF:*p++; } inline int read(){ int res = 0; char c = nc(); while(c<'0'||c>'9')c=nc(); while(c<='9'&&c>='0')res=res*10+c-'0',c=nc(); return res; }  
 
int n, m;
int b[N][M], q[N][M], top[M];
ll d[N], sum[N], ans, a[N];//不开 long long 见祖宗
 
int main(){
	n = read(); m = read();
	for (int i = 2; i <= n; ++ i ) a[i] = read(), a[i] += a[i - 1];
	for (int i = 1; i <= n; ++ i ) 
		for (int j = 1; j <= m; ++ j ) 	
			b[i][j] = read();
	
	for (int r = 1; r <= n; ++ r ) {
		for (int j = 1; j <= m; ++ j ) {
			int last = 0; //last 就是b[l[k+1]][j]
			while(top[j] && b[q[top[j]][j]][j] < b[r][j]) {
//			if(r == 2)cout << d[q[top[j]][j]] << endl;
				d[q[top[j]][j]]	-= 1ll * (b[q[top[j]][j]][j] - last);
				last = b[q[top[j] -- ][j]][j];
			}
			d[q[top[j]][j]] -= 1ll * (b[r][j] - last); 
			q[ ++ top[j]][j] = r; 
			d[q[top[j]][j]] += 1ll * b[r][j];
        //刚刚的差分
		}
		for (int l = r; l >= 1; -- l ) {
			sum[l] = sum[l + 1] + d[l];
//			cout << l << " " << r << "->" << d[l] << endl;
			ans = max(ans, sum[l] - a[r] + a[l]);
		}
	} 
    printf("%lld", ans);
// 	fwrite(obuf,p3-obuf,1,stdout);
	return 0;
}

标签:le,int,题解,sum,差分,arc067,buf,单调
From: https://www.cnblogs.com/Raining-Hard/p/17515217.html

相关文章

  • ABC143F 题解
    前言题目传送门!更好的阅读体验?很有趣的题。提供一种和现有题解略微不同的做法。思路突破点在于反着想。当最多能取\(x\)次时,每次我取的不同数字的数量,最多是多少。统计一下每个数字出现的次数\(cnt_i\)。那么这个最多次数应为\[\left\lfloor\dfrac{\sum\min(cnt_i,x)}x......
  • 「ARC133E」Cyclic Medians 题解
    本文网址:https://www.cnblogs.com/zsc985246/p/17513317.html,转载请注明出处。传送门「ARC133E」CyclicMedians题目大意给定\(n,m,V,A\),你需要计算所有长为\(n\)、值域为\([1,V]\)的整数序列\(x\)和长为\(m\)、值域为\([1,V]\)的整数序列\(y\)形成的序列对\((x_......
  • Codeforces[CF1036B]Diagonal Walking v.2题解
    题目大意很明显,这道题就是求k步之内到达点\((a,b)\),然后尽量走对角线,求能走对角线的最大值。做题思路首先明白一个事实,即一个对角线可以通过增加一步而抵达点不变,如图:我们可以这样思考这道题,在到达目的地以后,剩余步数如果为双数,则在对角线来回走,最后会到目的地。但如果剩......
  • Switches and Lamps 题解
    题目传送门一道枚举题。首先我们需要知道什么开关才能被去掉,题目要求去掉这个开关后所有的灯依然能够开启。也就是说,这个开关能打开的所有灯都可以由其它开关代替。思路清晰了,就比较好做。我们可以用一个数组存储下每一盏灯可以被几个开关开启,如果有一盏灯只能被\(1\)个开关......
  • P1552 [APIO2012] 派遣 题解
    一、题目描述:给你一个$n$个点的有根树,每个点有两个参数$w$和$v$。再给出一个数$m$。对于每一个点$u$,设它的子树内最多可以选择$k_u$个点$a_1,a_2,...,a_{k_u}$,使得$\sum_{i=1}^kw_{a_i}\lem$。那么点$u$的价值为$v_u\timesk_u$,求$max(\su......
  • 前端打包部署后接口BASE_URL不对问题解决办法
    在前端打包部署时,为了免去不同环境打包的麻烦,项目用的流水线触发方式。在这里不细说,重点说说下面情况。当项目提交打包部署后,访问压测环境或者生产环境的地址来使用项目时,发现接口报错404。 在NETWORK里发现接口的BASEURL和当前环境需要调用的后端baseurl不同。主要问题在于......
  • 解密2.0题解
    解密题目首先查看题目的\(\LaTeX\)源代码,发现在答案后面有一个。可以点击。点击这个句号,来到线索\(1\)。线索\(1\):在源代码里发现有base64这个字眼,于是就把后面一长串的字符aW46MiAzCm91dDpKYXNvbmN3eCBjYW4ndCBBSyBDU1BK扔到base64解密。解密得出:in:23out:Jasoncwx......
  • CF1834 题解
    CF1834题解A考虑答案与元素位置无关,只与\(1\)和\(-1\)的个数有关。要求\(1\)必须多于或等于\(-1\),并且\(-1\)个数为偶数。分讨:序列中\(num(1)\geqnum(-1)\),只需要看\(num(-1)\)正负性,奇数1步,偶数0步序列中\(num(1)<num(-1)\),先通过\(-1\)变\(1\)将数目补到第一种情况,再做......
  • mac打开ddms卡住的问题解决
    https://blog.csdn.net/qq_35244415/article/details/110656444?spm=1001.2101.3001.6650.1&utm_medium=distribute.pc_relevant.none-task-blog-2~default~CTRLIST~Rate-1-110656444-blog-88994745.235^v38^pc_relevant_default_base&depth_1-utm_source=distribute.......
  • P4630 [APIO2018] 铁人两项 题解
    一、题目描述:给你一个$n$个点,$m$条边的无向图。图不一定联通求出点对$(u,c,v)$的数量,使得点$u$存在一条经过点$c$到达点$v$的无向图。数据范围:$1\len\le1\times10^5,1\lem\le2\times10^5$ 二、解题思路:算是圆方树比较模板的题了......