首页 > 其他分享 >题解:AT_abc140_e [ABC140E] Second Sum

题解:AT_abc140_e [ABC140E] Second Sum

时间:2024-08-21 15:05:34浏览次数:7  
标签:pre nxt abc140 题解 ll Second 数大 l1 id

思路:双向链表+组合数学(不过你要用单调栈也没人拦着你)

我们现在先抛开题面,先换个思路。

我们现在求:这个数能做多少个区间的次大值

我们现在设 \(l1, l2, r1, r2\) 分别为左边第一个比这个数大的 id,第二个比这个数大的 id,右边第一个比这个数大的 id,第二个比这个数大的 id。竟然是次大值,所以我们左边和右边能且仅能包含一个比这个数大的。

我们现在求区间数即为:

  • 左边取一个比他大的数的个数 \(\times\) 右边取不比他大的数的个数。
  • 右边取一个比他大的数的个数 \(\times\) 左边取不比他大的数的个数。

即为:

  • (l1 - l2) * (r1 - a[i].id)
  • (r2 - r1) * (a[i].id - l1)

那么如何获得 \(l1, l2, r1, r2\) 呢

如果我能直接从当前这个数找到这四个数是最好的,就是说像这样的一个链表:

要实现这样我们可以存好 id 后排序,从小到大处理,根据链表的删除机制,到某个数时,一定会成为类似上图的样子。

代码:

#include <bits/stdc++.h>
#define ll long long
using namespace std;

ll n;
struct Node
{
    ll x;
    ll id;
} a[100005];
ll pre[100005], nxt[100005];
ll ans = 0;
bool cmp(Node a, Node b) {
	return a.x < b.x;
}
void del(ll id)
{
	nxt[pre[id]] = nxt[id];
	pre[nxt[id]] = pre[id];
	return ;
}

int main()
{
    cin >> n;
    for (ll i = 1; i <= n; i++)
    {
    	cin >> a[i].x;
    	a[i].id = i;
    	pre[i] = i - 1;
    	nxt[i] = i + 1;
	}
	nxt[0] = 1;
	pre[n + 1] = n;
	sort(a + 1, a + n + 1, cmp);
	for (ll i = 1; i <= n; i++)
	{
		ll l1, l2, r1, r2;
		// left
		l1 = pre[a[i].id];
		if (l1) l2 = pre[l1];
		else l2 = -1;
		// right
		r1 = nxt[a[i].id];
		if (r1 != n + 1) r2 = nxt[r1];
		else r2 = -1;
		// solve
		if (!(l2 == -1))
			ans += (l1 - l2) * (r1 - a[i].id) * a[i].x;
		if (!(r2 == -1))
			ans += (r2 - r1) * (a[i].id - l1) * a[i].x;
		del(a[i].id);
	}
	cout << ans << "\n";
	return 0;
}

标签:pre,nxt,abc140,题解,ll,Second,数大,l1,id
From: https://www.cnblogs.com/George222/p/18371664

相关文章

  • 题解:Codeforces Round 967 (Div. 2) [暴力/贪心]
    A.MakeAllEqualtimelimitpertest:1secondmemorylimitpertest:256megabytesinput:standardinputoutput:standardoutputYouaregivenacyclicarray\(a_1,a_2,\ldots,a_n\).Youcanperformthefollowingoperationon\(a\)atmost\(n-......
  • 题解 |栈| #中缀表达式求值!!!!#
    描述请写一个整数计算器,支持加减乘三种运算和括号。数据范围:0≤∣s∣≤1000≤∣s∣≤100,保证计算结果始终在整型范围内要求:空间复杂度: O(n)O(n),时间复杂度 O(n)O(n)示例1输入:"1+2"返回值:3示例2输入:"(2*(3-4))*5"返回值:-10示例3输入:"3+2*3*4-1"返回值:26一、使......
  • [ABC132F] Small Products 题解
    题意一句话题意不用再翻译了吧。思路先考虑朴素的dp,设\(dp_{i,j}\)表示长度为\(i\)结尾数字为\(j\)的序列的方案数,状态很好转移:\[dp_{i,j}=\sum_{a=1}^{\lfloor\frac{N}{j}\rfloor}dp_{i-1,a}\]这样时间复杂度是\(\Theta(nk)\)的,显然过不了。考虑优化这个dp。......
  • [ABC156E] Roaming 题解
    前言这哪有蓝,评分似乎有点过了。思路既然是要统计每个房间人数的排列,那我们就枚举把所有人都放到\(i\)个房间里的方案数,这个用插板法解决,把所有人都放到\(i\)个房间里也就是把他们分成\(i\)份,这一部分的答案就是在\(n\)个人的\(n-1\)个空中插入\(i-1\)块隔板的方案......
  • 题解:P10724 [GESP202406 七级] 区间乘积
    思路当一个数是完全平方数的时候,它的所有质因子的次数都是偶数。记\(x\)的质因子为\(p_1^{q1}\timesp_2^{q2}\timesp_3^{q3}...\timesp_v^{qv}\)。这些数可以通过次数的奇偶性用一个\(v\)位的二进制串\(B\)表示,\(B_i\)为\(0\)说明\(q_i\)为偶数,\(B_i\)为\(......
  • [题解]P3311 [SDOI2014] 数数
    P3311[SDOI2014]数数看到多模式匹配,我们考虑先对所有模式串建立AC自动机。然后发现这道题和P4052文本生成器(题解)挺像的,后者让求包含至少一个模式串的个数,这道题让求一个也不包含的个数,这个就是一个用不用\(26^m\)去减的问题,很好处理。但这道题还多了一个条件,“幸运数”必须\(......
  • Prometheus部署以及问题解决
    Prometheus作用:Prometheus监控(PrometheusMonitoring)是一种开源的系统监控和警报工具。它最初由SoundCloud开发并于2012年发布,并在2016年加入了云原生计算基金会(CNCF)。Prometheus监控旨在收集、存储和查询各种指标数据,以帮助用户监视其应用程序和系统的性能和运行状态。部署流......
  • 题解:CF454B Little Pony and Sort by Shift
    题目描述题目传送门给定一个长度为$n$的数组$a$,每次可以将最后一个元素移动到第一个,问:至少需要几次操作,让序列从小到大排好序,若无解输出$-1$。算法1(暴力枚举)不难想到,将最后一个元素拼接在第一个元素之前,就可以实现将链转换成环,再依次遍历在数组$a_i$中长度为$n$的......
  • Postman中Body添加注释后请求报错问题解决【保姆级教程!!!】
    本文介绍关于Postman中Body添加注释后请求报错问题解决方法如:请求返回下述报错操作失败!系统异常,JsonParseException:Unexpectedcharacter(‘/’(code47)):maybea(non-standard)comment?(notrecognizedasonesinceFeature‘ALLOW_COMMENTS’notenabled......
  • P2261 [CQOI2007] 余数求和 题解
    题目传送门思路数学数学非常经典的题目注意到\(k\bmodi=k-\lfloork/i\rfloor*i\)。于是可以对题目进行转化,从求\(G(n,k)=\sum_{i=1}^kn\bmodi\)变为求\(G(n,k)=n\timesk-\sum_{i=1}^n\lfloork/i\rfloor\timesi\),所以仅需求出\(\sum_{i......