题意

给定一个长度为 \(n\) 的序列 \(\{a_i\}\)。你需要从该序列中选出两个非空的子段,这两个子段满足

  • 两个子段非包含关系。
  • 两个子段存在交。
  • 位于两个子段交中的元素在每个子段中只能出现一次。

求共有多少种不同的子段选择方案。输出总方案数对 \(10^9 + 7\) 取模后的结果。

需要注意的是,选择子段 \([a, b]\)、\([c, d]\) 与选择子段 \([c, d]\)、\([a, b]\) 被视为是相同的两种方案。

\(1 \leq n \leq 10^5, -10^9 \leq a_i \leq 10^9\)。

分析

  • 考虑枚举一个区间 \([b,c]\) 作为交,记录 \(L_i,R_i\) 表示距离 \(i\) 最近的和 \(i\) 颜色相同的位置。

  • 有: \(a\in[\max\limits_{i=b}^c{L_i},b),d\in(c,\min\limits_{i=b}^c{R_i}]\)。

  • 记录可以取到的左端点的最小值(满足区间中不存在两个相同的数) \(pos\) 。 \(mi, mx\) 分别表示 \([j,i]\) 中 \(R\) 的极小值和 \(L\) 的极大值。

  • 考虑从左到右枚举交区间的右端点 \(i\) ,用单调栈维护每个位置的 \(mi, mx\) 。容易得到以 \(i\) 为交区间的右端点的方案数为 \(\sum_{j=pos}^i(mi_j-i)(j-mx_j)​\),拆开然后用线段树分别维护。

  • 总时间复杂度为 \(O(nlogn)\)。

代码

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
#define go(u) for(int i = head[u], v = e[i].to; i; i=e[i].lst, v=e[i].to)
#define rep(i, a, b) for(int i = a; i <= b; ++i)
#define pb push_back
#define re(x) memset(x, 0, sizeof x)
inline int gi() {
int x = 0,f = 1;
char ch = getchar();
while(!isdigit(ch)) { if(ch == '-') f = -1; ch = getchar();}
while(isdigit(ch)) { x = (x << 3) + (x << 1) + ch - 48; ch = getchar();}
return x * f;
}
template <typename T> inline void Max(T &a, T b){if(a < b) a = b;}
template <typename T> inline void Min(T &a, T b){if(a > b) a = b;}
const int N = 1e5 + 7, mod = 1e9 + 7;
int n, vc;
LL ans;
int lst[N], L[N], R[N], V[N], a[N];
int st1[N], st2[N], tp1, tp2;
#define Ls o << 1
#define Rs (o << 1 | 1)
LL s1(int n) {
return 1ll * n * (n + 1) / 2;
}
LL ami[N << 2], amx[N << 2];
struct data {
LL mi, mx, smi, tm;
data operator +(const data &rhs) const {
return (data){ (mi + rhs.mi) % mod, (mx + rhs.mx) % mod, (smi + rhs.smi) % mod, (tm + rhs.tm) % mod};
}
}t[N << 2];
void add(LL &a, LL b) {
a += b;if(a >= mod) a -= mod;
}
void stmi(int l, int r, int o, int v) {
add(ami[o], v);
add(t[o].tm, 1ll * v * t[o].mx % mod);
add(t[o].mi, 1ll * (r - l + 1) * v % mod);
add(t[o].smi, (s1(r) - s1(l - 1)) % mod * v % mod);
}
void stmx(int l, int r, int o, int v) {
add(amx[o], v);
add(t[o].tm, 1ll * v * t[o].mi % mod);
add(t[o].mx, 1ll * (r - l + 1) * v % mod);
}
void pushdown(int l, int r, int o) {
int mid = l + r >> 1;
if(ami[o]) {
stmi(l, mid, Ls, ami[o]);
stmi(mid + 1, r, Rs, ami[o]);
}
if(amx[o]) {
stmx(l, mid, Ls, amx[o]);
stmx(mid + 1, r, Rs, amx[o]);
}
ami[o] = amx[o] = 0;
}
void pushup(int o) {
t[o] = t[Ls] + t[Rs];
}
void modify(int L, int R, int l, int r, int o, int v, int opt) {
if(L <= l && r <= R) {
if(!opt) stmi(l, r, o, v);
else stmx(l, r, o, v);
return;
}
pushdown(l, r, o);int mid = l + r >> 1;
if(L <= mid) modify(L, R, l, mid, Ls, v, opt);
if(R > mid) modify(L, R, mid + 1, r, Rs, v, opt);
pushup(o);
}
data query(int L, int R, int l, int r, int o) {
if(L <= l && r <= R) return t[o];
pushdown(l, r, o);int mid = l + r >> 1;
if(R <= mid) return query(L, R, l, mid, Ls);
if(L > mid) return query(L, R, mid + 1, r, Rs);
return query(L, R, l, mid, Ls) + query(L, R, mid + 1, r, Rs);
}
int main() {
n = gi();
rep(i, 1, n) a[i] = gi(), V[i] = a[i];
sort(V + 1, V + 1 + n);
vc = unique(V + 1, V + 1 + n) - V - 1;
rep(i, 1, n) a[i] = lower_bound(V + 1, V + 1 + vc, a[i]) - V;
rep(i, 1, n) {
L[i] = lst[a[i]] + 1;
lst[a[i]] = i;
}
rep(i, 1, vc) lst[i] = n + 1;
for(int i = n; i; --i) {
R[i] = lst[a[i]] - 1;
lst[a[i]] = i;
}
for(int i = 1, gg = 1; i <= n; ++i) {
for(; tp1 && L[i] >= L[st1[tp1]]; --tp1) {
modify(st1[tp1 - 1] + 1, st1[tp1], 1, n, 1, mod - L[st1[tp1]], 1);
}
modify(st1[tp1] + 1, i, 1, n, 1, L[i], 1);
st1[++tp1] = i;
for(; tp2 && R[i] <= R[st2[tp2]]; --tp2) {
modify(st2[tp2 - 1] + 1, st2[tp2], 1, n, 1, mod - R[st2[tp2]], 0);
}
modify(st2[tp2] + 1, i, 1, n, 1, R[i], 0);
st2[++tp2] = i; Max(gg, L[i]);
data res = query(gg, i, 1, n, 1);
LL tmp = ((res.smi + i * res.mx % mod - res.tm - (s1(i) - s1(gg - 1)) % mod * i % mod) % mod + mod) % mod;
add(ans, tmp);
}
printf("%lld\n", ans);
return 0;
}

[CF1083D]The Fair Nut’s getting crazy[单调栈+线段树]的更多相关文章

  1. 洛谷P4198 楼房重建 单调栈+线段树

    正解:单调栈+线段树 解题报告: 传送门! 首先考虑不修改的话就是个单调栈板子题昂,这个就是 然后这题的话,,,我怎么记得之前考试好像有次考到了类似的题目昂,,,?反正我总觉着这方法似曾相识的样子,, ...

  2. 2018宁夏邀请赛 L Continuous Intervals(单调栈+线段树)

    2018宁夏邀请赛 L Continuous Intervals(单调栈+线段树) 传送门:https://nanti.jisuanke.com/t/41296 题意: 给一个数列A 问在数列A中有多 ...

  3. The Preliminary Contest for ICPC China Nanchang National Invitational I. Max answer (单调栈+线段树)

    题目链接:https://nanti.jisuanke.com/t/38228 题目大意:一个区间的值等于该区间的和乘以区间的最小值.给出一个含有n个数的序列(序列的值有正有负),找到该序列的区间最大 ...

  4. 2019南昌网络赛-I(单调栈+线段树)

    题目链接:https://nanti.jisuanke.com/t/38228 题意:定义一段区间的值为该区间的和×该区间的最小值,求给定数组的最大的区间值. 思路:比赛时还不会线段树,和队友在这题上 ...

  5. 网络赛 I题 Max answer 单调栈+线段树

    题目链接:https://nanti.jisuanke.com/t/38228 题意:在给出的序列里面找一个区间,使区间最小值乘以区间和得到的值最大,输出这个最大值. 思路:我们枚举每一个数字,假设是 ...

  6. 南昌邀请赛I.Max answer 单调栈+线段树

    题目链接:https://nanti.jisuanke.com/t/38228 Alice has a magic array. She suggests that the value of a in ...

  7. 【CF671E】Organizing a Race 单调栈+线段树

    [CF671E]Organizing a Race 题意:n个城市排成一排,每个城市内都有一个加油站,赛车每次经过第i个城市时都会获得$g_i$升油.相邻两个城市之间由道路连接,第i个城市和第i+1个 ...

  8. 南昌网络赛 I. Max answer (单调栈 + 线段树)

    https://nanti.jisuanke.com/t/38228 题意给你一个序列,对于每个连续子区间,有一个价值,等与这个区间和×区间最小值,求所有子区间的最大价值是多少. 分析:我们先用单调栈 ...

  9. 2019ICPC南昌邀请赛网络赛 I. Max answer (单调栈+线段树/笛卡尔树)

    题目链接 题意:求一个序列的最大的(区间最小值*区间和) 线段树做法:用单调栈求出每个数两边比它大的左右边界,然后用线段树求出每段区间的和sum.最小前缀lsum.最小后缀rsum,枚举每个数a[i] ...

随机推荐

  1. tomcat报错this web application instance has been stopped already问题

    上网搜了下,大部分的报错原因:重启时候 之前的tomcat未正常关闭 ,导致在重启时候 报了这个问题.mac下解决: ps -ef|grep tomcat 找到在进行的tomcat ,kill -9  ...

  2. Oracle EBS INV 释放保留

    CREATE or REPPLACE PROCEDURE RelieveReservation AS -- Common Declarations l_api_version NUMBER := 1. ...

  3. ecplice 中添加JavaFX插件学习

    fxml文件使用SceneBuilder打开报错 解决方法:Window-->Preferences-->JavaFX-->browse 路径是可执行的JavaFX Scene Bu ...

  4. 56_实现类似spring的可配置的AOP框架

    > config.properties  配置文件   key=类名 > BeanFactory  Bean工厂,负责得到bean  getBean("xxx") &g ...

  5. 2.HBase In Action 第一章-HBase简介(1.1数据管理系统:快速学习)

    Relational database systems have been around for a few decades and have been hugely successful in so ...

  6. Android与js交互拍照上传资料

    应用场景:h5通知android端拍照,选相册,然后将图片路径上传成功之后,获取到网络路径,将此路径返还给h5界面,并展示出来. android与js快速交互 效果图如下:   1.在Activity ...

  7. sql server 数据库作业备份存储过程

    DECLARE @fileName nvarchar(100) SET @fileName='D:\HFS\DataBase' + REPLACE(REPLACE(REPLACE(REPLACE(CO ...

  8. docker中使用的镜像加速器可以自己生成

    只要你到该网址https://cr.console.aliyun.com/cn-hangzhou/mirrors登录(我使用的是支付宝帐号),然后你如下图操作,就能够看见你的加速器地址了,只要你登录就 ...

  9. RedHat 7.3 Oracle 12.2.0.1 RAC 安装手册(转)

    1  准备工作 1.1   关于GRID的一些变化 1.1.1  简化的基于映像的Oracle Grid Infrastructure安装 从Oracle Grid Infrastructure 12 ...

  10. leetcode 200. Number of Islands 、694 Number of Distinct Islands 、695. Max Area of Island 、130. Surrounded Regions

    两种方式处理已经访问过的节点:一种是用visited存储已经访问过的1:另一种是通过改变原始数值的值,比如将1改成-1,这样小于等于0的都会停止. Number of Islands 用了第一种方式, ...