题意

题目链接

Sol

线段树板子题都做不出来,真是越来越菜了。。

根据题目描述,一个合法区间等价于在区间内的颜色没有在区间外出现过。

所以我们可以对于每个右端点,统计最长的左端点在哪里,刚开始以为这个东西有单调性,但事实并不是这样。。

我们统计出对于每个颜色最优的位置\(r_i\)和最左的位置\(l_i\)

那么对于某个左端点\(j\),如果\(r_j > i\),那么\(j\)以及它左侧的点都是不能选的,这里可以用堆+multiset维护。

若\(r_j \leqslant i\),那么\((l_j, r_j]\)都是不能选的。

然后直接线段树区间赋值就好了

// luogu-judger-enable-o2
#include<bits/stdc++.h>
#define Fin(x) freopen(#x".in", "r", stdin);
#define Pair pair<int, int>
#define fi first
#define se second
template<typename A, typename B> inline bool chmax(A &x, B y) {return x < y ? x = y, 1 : 0;}
template<typename A, typename B> inline bool chmin(A &x, B y) {return x > y ? x = y, 1 : 0;}
#define LL long long
using namespace std;
const int MAXN = 2e6 + 10, INF = 1e9 + 10;
inline int read() {
char c = getchar(); int x = 0, f = 1;
while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();}
while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
return x * f;
}
int N, a[MAXN], r[MAXN], l[MAXN], tag[MAXN];
multiset<int> s;
priority_queue<Pair, vector<Pair>, greater<Pair> > q;
void Erase(int x) {
auto it = s.find(x);
s.erase(it);
}
#define ls k << 1
#define rs k << 1 | 1
int f[MAXN], sum[MAXN];
void update(int k) {
sum[k] = sum[ls] + sum[rs];
}
void ps(int k) {
sum[k] = 0; f[k] = 1;
}
void pushdown(int k) {
if(!f[k]) return ;
ps(ls); ps(rs);
f[k] = 0;
}
void Build(int k, int l, int r) {
f[k] = 0;
if(l == r) {sum[k] = 1; return ;}
int mid = l + r >> 1;
Build(ls, l, mid); Build(rs, mid + 1, r);
update(k);
}
int Query(int k, int l, int r, int ql, int qr) {
if(ql <= l && r <= qr) return sum[k];
pushdown(k);
int mid = l + r >> 1;
if(ql > mid) return Query(rs, mid + 1, r, ql, qr);
else if(qr <= mid) return Query(ls, l, mid, ql, qr);
else return Query(ls, l, mid, ql, qr) + Query(rs, mid + 1, r, ql, qr);
}
void Mem(int k, int l, int r, int ql, int qr) {
if(ql <= l && r <= qr) {ps(k); return ;}
pushdown(k);
int mid = l + r >> 1;
if(ql <= mid) Mem(ls, l, mid, ql, qr);
if(qr > mid) Mem(rs, mid + 1, r, ql, qr);
update(k);
}
void solve() {
N = read(); int mx = 0;
for(int i = 1; i <= N; i++) l[i] = INF, r[i] = 0, tag[i] = 0;
for(int i = 1; i <= N; i++) a[i] = read(), chmax(r[a[i]], i), chmin(l[a[i]], i), chmax(mx, a[i]);
Build(1, 1, N);
LL ans = 0;
for(int i = 1; i <= N; i++) {
q.push({r[a[i]], i}); s.insert(i);
if(r[a[i]] == i)
if(l[a[i]] + 1 <= i) Mem(1, 1, N, l[a[i]] + 1, i);
int mx = 0;
while(!q.empty() && q.top().fi <= i)
Erase(q.top().se), q.pop();
if(!s.empty()) {
auto it = s.end(); it--;
mx = (*it);
}
if(mx + 1 <= i) ans += Query(1, 1, N, mx + 1, i);
}
cout << ans << '\n';
}
signed main() {
// Fin(a);
for(int T = read(); T--; solve());
return 0;
}

洛谷P4065 [JXOI2017]颜色(线段树)的更多相关文章

  1. 【BZOJ】1012: [JSOI2008]最大数maxnumber /【洛谷】1198(线段树)

    Description 现在请求你维护一个数列,要求提供以下两种操作:1. 查询操作.语法:Q L 功能:查询当前数列中末尾L个数中的最大的数,并输出这个数的值.限制:L不超过当前数列的长度.2. 插 ...

  2. 洛谷题解P4314CPU监控--线段树

    题目链接 https://www.luogu.org/problemnew/show/P4314 https://www.lydsy.com/JudgeOnline/problem.php?id=30 ...

  3. 洛谷P3372/poj3468(线段树lazy_tag)(询问区间和,支持区间修改)

    洛谷P3372 //线段树 询问区间和,支持区间修改 #include <cstdio> using namespace std; struct treetype { int l,r; l ...

  4. 洛谷P1558 色板游戏 [线段树]

    题目传送门 色板游戏 题目背景 阿宝上学了,今天老师拿来了一块很长的涂色板. 题目描述 色板长度为L,L是一个正整数,所以我们可以均匀地将它划分成L块1厘米长的小方格.并从左到右标记为1, 2, .. ...

  5. [JXOI2017]颜色 线段树扫描线 + 单调栈

    ---题面--- 题解: 首先题目要求删除一些颜色,换个说法就是要求保留一些颜色,那么观察到,如果我们设ll[i]和rr[i]分别表示颜色i出现的最左边的那个点和最右边的那个点,那么题目就是在要求我们 ...

  6. 洛谷P3707 [SDOI2017]相关分析(线段树)

    题目描述 Frank对天文学非常感兴趣,他经常用望远镜看星星,同时记录下它们的信息,比如亮度.颜色等等,进而估算出星星的距离,半径等等. Frank不仅喜欢观测,还喜欢分析观测到的数据.他经常分析两个 ...

  7. 洛谷$P2486\ [SDOI2011]$染色 线段树+树链剖分

    正解:线段树+树链剖分 解题报告: 传送门$QwQ$ 其实是道蛮板子的题,,,但因为我写得很呆然后写了贼久之后发现想法有问题要重构,就很难受,就先写个题解算了$kk$ 考虑先跑个树剖,然后按$dfn$ ...

  8. 洛谷P5111 zhtobu3232的线段树

    题意:给定线段树,上面若干个节点坏了,求能表示出多少区间. 区间能被表示出当且仅当拆出来的log个节点都是好的. 解:每个区间在最浅的节点处计算答案. 对于每个节点维护从左边过来能有多少区间,从右边过 ...

  9. 洛谷P3960 列队 NOIp2017 线段树/树状数组/splay

    正解:动态开点线段树 解题报告: 传送门! 因为最近学主席树的时候顺便get到了动态开点线段树?刚好想起来很久很久以前就想做结果一直麻油做的这题,,,所以就做下好了QAQ 然后说下,这题有很多种方法, ...

随机推荐

  1. Docker简介以及操作

    Docker 简介 Docker 是一个开源项目,诞生于 2013 年初,最初是 dotCloud 公司内部的一个业余项目.它基于 Google 公司推出的 Go 语言实现. 项目后来加入了 Linu ...

  2. 在Go语言中基础的Redis操作

    在Go语言中基础的Redis操作 需要先安装redigo go get "github.com/garyburd/redigo/redis" Go语言Redis客户端的简单示例 连 ...

  3. mysql 开发进阶篇系列 8 锁问题 (共享锁与排它锁演示)

    1 .innodb 共享锁(lock in share mode)演示 会话1 会话2 SET autocommit=0; SELECT cityname FROM  city WHERE city_ ...

  4. C++版 - 剑指offer 面试题24:二叉搜索树BST的后序遍历序列(的判断) 题解

    剑指offer 面试题24:二叉搜索树的后序遍历序列(的判断) 题目:输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果.如果是则返回true.否则返回false.假设输入的数组的任意两个 ...

  5. iptables防火墙常用配置介绍

    参考地址 http://www.cnblogs.com/metoy/p/4320813.html http://netfilter.org/ iptables http://man.chinaunix ...

  6. MySql数据库安装

    MySql数据库安装 一丶数据库 什么是数据库 数据库简单连接就是存储数据的容器. 而库则是一组容器合成的东西. 也就是存储数据的.我们编程中常常会用到数据库. 什么是数据管理系统 数据库管理系统就是 ...

  7. 【转载】红外遥控HS0038B接法

        4.7uF电容的作用:去耦和旁路   去耦电容的主要功能就是提供一个局部的直流电源给有源器件,以减少开关噪声在板上的传播和将噪声引导到地.通常也把输出信号的干扰作为滤除对象. 旁路电容:为高频 ...

  8. Java 并发编程-再谈 AbstractQueuedSynchronizer 2:共享模式与基于 Condition 的等待 / 通知机制实现

    共享模式acquire实现流程 上文我们讲解了AbstractQueuedSynchronizer独占模式的acquire实现流程,本文趁热打铁继续看一下AbstractQueuedSynchroni ...

  9. 使用Eclipse创建SpringBoot项目

    1  首先我们需要安装STS插件:Help--> Eclipse Marketplace 安装成功之后,会让你重启eclipse. 2  然后 File-->New--->Proje ...

  10. Docker数据卷Volume实现文件共享、数据迁移备份(三)--技术流ken

    前言 前面已经写了两篇关于docker的博文了,在工作中有关docker的基本操作已经基本讲解完了.相信现在大家已经能够熟练配置docker以及使用docker来创建镜像以及容器了.本篇博客将会讲解如 ...