题解

我们枚举右端点判断合法的左端点有哪些

首先,记录一下右端点右边的点的pre,也就是这个数字前一个出现的位置,取所有小于枚举右端点r的值中最大的一个做为l,用优先队列维护即可,[l + 1,r]就是可能取到的左端点的区间

然后我们对于每一种数字,最前一次出现的位置p,最后一次出现的位置q,覆盖[p + 1,q]这段区间作为不能填的区间,用线段树维护一下,用可取的左端点区间减掉不能填的地方

如果右端点出现过了,那么删除这种数字的覆盖区间,可以在右端点左移的时候同时干这件事

代码

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <vector>
#include <set>
#include <cmath>
#include <bitset>
#include <queue>
#define enter putchar('\n')
#define space putchar(' ')
//#define ivorysi
#define pb push_back
#define mo 974711
#define pii pair<int,int>
#define mp make_pair
#define fi first
#define se second
#define MAXN 200005
using namespace std;
typedef long long int64;
typedef double db;
template<class T>
void read(T &res) {
res = 0;char c = getchar();T f = 1;
while(c < '0' || c > '9') {
if(c == '-') f = -1;
c = getchar();
}
while(c >= '0' && c <= '9') {
res = res * 10 - '0' + c;
c = getchar();
}
res = res * f;
}
template<class T>
void out(T x) {
if(x < 0) {x = -x;putchar('-');}
if(x >= 10) out(x / 10);
putchar('0' + x % 10);
}
int N;
int a[MAXN],minn[MAXN],maxx[MAXN],pre[MAXN],last[MAXN],vis[MAXN];
int64 ans;
priority_queue<int> Q;
struct node {
int l,r,cover,sum;
}tr[MAXN * 4];
void build(int u,int l,int r) {
tr[u].l = l;tr[u].r = r;
tr[u].cover = 0;tr[u].sum = 0;
if(l == r) return;
int mid = (l + r) >> 1;
build(u << 1,l,mid);
build(u << 1 | 1,mid + 1,r);
}
void addcover(int u,int v) {
tr[u].cover += v;
if(tr[u].cover) tr[u].sum = tr[u].r - tr[u].l + 1;
else tr[u].sum = tr[u << 1].sum + tr[u << 1 | 1].sum;
}
void update(int u) {
if(tr[u].cover) tr[u].sum = tr[u].r - tr[u].l + 1;
else tr[u].sum = tr[u << 1].sum + tr[u << 1 | 1].sum;
}
void Add(int u,int l,int r,int on) {
if(l > r) return;
if(tr[u].l == l && tr[u].r == r) {
addcover(u,on);
return;
}
int mid = (tr[u].l + tr[u].r) >> 1;
if(r <= mid) Add(u << 1,l,r,on);
else if(l > mid) Add(u << 1 | 1,l,r,on);
else Add(u << 1,l,mid,on),Add(u << 1 | 1,mid + 1,r,on);
update(u);
}
int Query(int u,int l,int r) {
if(tr[u].cover) return r - l + 1;
if(tr[u].l == l && tr[u].r == r) return tr[u].sum;
int mid = (tr[u].l + tr[u].r) >> 1;
if(r <= mid) return Query(u << 1,l,r);
else if(l > mid) return Query(u << 1 | 1,l,r);
else return Query(u << 1,l,mid) + Query(u << 1 | 1,mid + 1,r);
}
void Solve() {
while(!Q.empty()) Q.pop();
read(N);
build(1,1,N);
ans = 0;
for(int i = 1 ; i <= N ; ++i) {
read(a[i]);
minn[i] = N;maxx[i] = 0;
pre[i] = 0;last[i] = 0;
}
for(int i = 1 ; i <= N ; ++i) {
minn[a[i]] = min(minn[a[i]],i);
maxx[a[i]] = max(maxx[a[i]],i);
}
for(int i = 1 ; i <= N ; ++i) {
if(!vis[a[i]]) {
Add(1,minn[a[i]] + 1,maxx[a[i]],1);
vis[a[i]] = 1;
}
}
for(int i = 1 ; i <= N ; ++i) {
pre[i] = last[a[i]];
last[a[i]] = i;
}
Q.push(0);
for(int i = N ; i >= 1 ; --i) {
while(Q.top() > i) Q.pop();
int L = Q.top() + 1;
if(L <= i) {
int t = i - L + 1;
ans += t - Query(1,L,i);
}
Q.push(pre[i]);
if(vis[a[i]]) {
Add(1,minn[a[i]] + 1,maxx[a[i]],-1);
vis[a[i]] = 0;
}
}
out(ans);enter;
}
int main() {
#ifdef ivorysi
freopen("f1.in","r",stdin);
#endif
int T;
read(T);
while(T--) {
Solve();
}
}

【LOJ】#2275. 「JXOI2017」颜色的更多相关文章

  1. loj2275 「JXOI2017」颜色

    枚举右端点,然后看左端点合法情况. 先预处理每个颜色 \(i\) 的最大出现位置 \(max_i\) 和最小出现位置 \(min_i\).对于枚举右端点在一个位置 \(i\),凡是 \(max_k & ...

  2. Loj #3057. 「HNOI2019」校园旅行

    Loj #3057. 「HNOI2019」校园旅行 某学校的每个建筑都有一个独特的编号.一天你在校园里无聊,决定在校园内随意地漫步. 你已经在校园里呆过一段时间,对校园内每个建筑的编号非常熟悉,于是你 ...

  3. Loj #3111. 「SDOI2019」染色

    Loj #3111. 「SDOI2019」染色 题目描述 给定 \(2 \times n\) 的格点图.其中一些结点有着已知的颜色,其余的结点还没有被染色.一个合法的染色方案不允许相邻结点有相同的染色 ...

  4. Loj #2192. 「SHOI2014」概率充电器

    Loj #2192. 「SHOI2014」概率充电器 题目描述 著名的电子产品品牌 SHOI 刚刚发布了引领世界潮流的下一代电子产品--概率充电器: 「采用全新纳米级加工技术,实现元件与导线能否通电完 ...

  5. Loj #3096. 「SNOI2019」数论

    Loj #3096. 「SNOI2019」数论 题目描述 给出正整数 \(P, Q, T\),大小为 \(n\) 的整数集 \(A\) 和大小为 \(m\) 的整数集 \(B\),请你求出: \[ \ ...

  6. Loj #3093. 「BJOI2019」光线

    Loj #3093. 「BJOI2019」光线 题目描述 当一束光打到一层玻璃上时,有一定比例的光会穿过这层玻璃,一定比例的光会被反射回去,剩下的光被玻璃吸收. 设对于任意 \(x\),有 \(x\t ...

  7. Loj #3089. 「BJOI2019」奥术神杖

    Loj #3089. 「BJOI2019」奥术神杖 题目描述 Bezorath 大陆抵抗地灾军团入侵的战争进入了僵持的阶段,世世代代生活在 Bezorath 这片大陆的精灵们开始寻找远古时代诸神遗留的 ...

  8. Loj #2542. 「PKUWC2018」随机游走

    Loj #2542. 「PKUWC2018」随机游走 题目描述 给定一棵 \(n\) 个结点的树,你从点 \(x\) 出发,每次等概率随机选择一条与所在点相邻的边走过去. 有 \(Q\) 次询问,每次 ...

  9. Loj #3059. 「HNOI2019」序列

    Loj #3059. 「HNOI2019」序列 给定一个长度为 \(n\) 的序列 \(A_1, \ldots , A_n\),以及 \(m\) 个操作,每个操作将一个 \(A_i\) 修改为 \(k ...

随机推荐

  1. P3007 [USACO11JAN]大陆议会The Continental Cowngress

    P3007 [USACO11JAN]大陆议会The Continental Cowngress 题意: 给出 n 个法案, m 头牛的意见, 每头牛有两个表决 格式为 "支持或反对某法案&q ...

  2. java基础-迭代器(Iterator)与增强for循环

    java基础-迭代器(Iterator)与增强for循环 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.Iterator迭代器概述 Java中提供了很多个集合,它们在存储元素时 ...

  3. Showbo.js弹窗实现(jquery)

    一.搭建环境 下载showBo.js和showBo.css 下载链接:https://pan.baidu.com/s/1iUUlKXFNXCBEvBnds4ECIA  密码:its4 显示效果图: 二 ...

  4. 如何在Windows系统下隐藏文件

    隐藏后只有键入文件夹名称才可访问,如果忘记路径就找不到了 attrib +s +a +h +r e:\bak\tools 取消的方法: attrib -a -s -h -r e:\bak\tools

  5. TV 开发相关

    1.设置全屏,隐藏虚拟按键 1.activity oncreate中 @Override 2 protected void onCreate (Bundle savedInstanceState) { ...

  6. 牛市必备的三个条件,A股现在还差几个

    1.国家政策 2.中美贸易 3.资金支持 A股变化如神! 自本月10日受美股大跌的影响后,A股先是随之震荡跳水,千股跌停:随后因高层力挺和政策支持而V型反转,集体涨停:接着上演过山车走势,有时涨得令人 ...

  7. codeforces9D How many trees?

    传送门:http://codeforces.com/problemset/problem/9/D [题解] 树形dp,f(i,j)表示i个节点,高度为j的方案数,枚举左子树大小和哪一个子树高度为j-1 ...

  8. java基础学习:JavaWeb之Cookie和Session

    一.会话概述 1.1.什么是会话? 会话可简单理解为:用户开一个浏览器,点击多个超链接,访问服务器多个web资源,然后关闭浏览器,整个过程称之为一个会话其中不管浏览器发送多少请求,都视为一次会话,直到 ...

  9. CodeForces 714A

    Description Today an outstanding event is going to happen in the forest — hedgehog Filya will come t ...

  10. HTTP请求方法 之 HEAD

    HTTP请求方法并不是只有GET和POST,只是最常用的.据RFC2616标准(现行的HTTP/1.1)得知,通常有以下8种方法:OPTIONS.GET.HEAD.POST.PUT.DELETE.TR ...