[JXOI2017]颜色
\(Orz\) 各位题解大佬,我来膜拜一发
还有单调栈实在没弄懂
法一:线段树+堆
首先,讨论区间的个数的题目,我们可以想到枚举一个端点\(r\),找到所有的\(l\)
我们不妨设:\(ml[i]\)为第i种颜色出现的最小位置,\(mr[i]\)为第i种出现的最大位置
我们想到对于一个右端点,他有那些值是不能选的:
假设有一种颜色的\(mr\)值比当前枚举的右端点小,则\([ml, mr]\)里面的所有的左端点都不能选,对应到线段树中就是区间赋成0
再假设有一种颜色,当前枚举的右端点在\([ml[i], mr[i]]\)之间,那么我们记录一个\(last[i]\),表示小于当前右端点的最大的i
那么\([1, last[i]]\)所有的值都不能选
然后我们要找到一个最大的last,用一个堆即可
#include<bits/stdc++.h>
using namespace std;
#define il inline
#define re register
#define int long long
il int read() {
re int x = 0, f = 1; re char c = getchar();
while(c < '0' || c > '9') { if(c == '-') f = -1; c = getchar();}
while(c >= '0' && c <= '9') x = x * 10 + c - 48, c = getchar();
return x * f;
}
#define rep(i, s, t) for(re int i = s; i <= t; ++ i)
#define mem(k, p) memset(k, p, sizeof(k))
#define ls k * 2
#define rs k * 2 + 1
#define maxn 300005
int n, m, a[maxn], last[maxn], ans, ml[maxn], mr[maxn], tag[maxn << 2], sum[maxn << 2];
struct node {int id, val; il bool operator < (const node&x) const{return val < x.val;}};
priority_queue<node> q;
il void pushdown(int k, int l, int r, int mid) {
if(tag[k] == -1) return;
sum[ls] = (mid - l + 1) * tag[k], sum[rs] = (r - mid) * tag[k];
tag[ls] = tag[rs] = tag[k]; tag[k] = -1;
}
il void modify(int k, int l, int r, int ll, int rr, int x) {
if(l > rr || ll > r) return;
if(ll <= l && r <= rr) return (void)(tag[k] = x, sum[k] = (r - l + 1) * x);
int mid = (l + r) >> 1; pushdown(k, l, r, mid);
modify(ls, l, mid, ll, rr, x), modify(rs, mid + 1, r, ll, rr, x);
sum[k] = sum[ls] + sum[rs];
}
il int query(int k, int l, int r, int ll, int rr) {
if(l > rr || ll > r) return 0;
if(ll <= l && r <= rr) return sum[k];
int mid = (l + r) >> 1; pushdown(k, l, r, mid);
return query(ls, l, mid, ll, rr) + query(rs, mid + 1, r, ll, rr);
}
il void solve() {
n = read(), ans = 0, mem(tag, -1), modify(1, 1, n, 1, n, 1);
while(!q.empty()) q.pop();
rep(i, 1, n) ml[i] = n + 1, mr[i] = last[i] = 0;
rep(i, 1, n) a[i] = read(), ml[a[i]] = min(ml[a[i]], i), mr[a[i]] = max(mr[a[i]], i);
rep(i, 1, n) {
last[a[i]] = i, q.push((node){a[i], last[a[i]]});
if(i == mr[a[i]]) modify(1, 1, n, ml[a[i]] + 1, mr[a[i]], 0);
while(!q.empty()) {
int x = q.top().id;
if(last[x] == mr[x]) q.pop();
else break;
}
int pax = (q.empty() ? 1 : q.top().val + 1);
ans += query(1, 1, n, pax, i);
}
printf("%lld\n", ans);
}
signed main() {
int T = read();
while(T --) solve();
return 0;
}
随机化
对于每一个位置,我们需要随机一个值,然后需要保证相同的颜色的所有的随机值异或结果为\(0\)
由于异或满足$a\ \(^\)\ b = 0$,所以我们把每个颜色的除了最后一项的所有随机值异或起来,让最后一位等于这个随机值
然后我们不难发现,每一个满足条件的一段区间,他的异或的值显然是等于0的
所以问题就转化成了:有多少区间的异或和等于0
由于上述异或的性质,于是我们只需要用\(map\)存一下即可
跟据@\(Ebola\)大佬的证明,我们的错误率是很小的。
\(Code:\)
#include<bits/stdc++.h>
using namespace std;
#define il inline
#define re register
#define debug printf("Now is Line : %d\n",__LINE__)
#define file(a) freopen(#a".in","r",stdin);freopen(#a".out","w",stdout)
#define int long long
il int read() {
re int x = 0, f = 1; re char c = getchar();
while(c < '0' || c > '9') { if(c == '-') f = -1; c = getchar();}
while(c >= '0' && c <= '9') x = x * 10 + c - 48, c = getchar();
return x * f;
}
#define rep(i, s, t) for(re int i = s; i <= t; ++ i)
#define drep(i, s, t) for(re int i = t; i >= s; -- i)
#define Next(i, u) for(re int i = head[u]; i; i = e[i].next)
#define mem(k, p) memset(k, p, sizeof(k))
#define lb(x) (x)&(-(x))
#define ls k * 2
#define rs k * 2 + 1
#define maxn 300005
int n, m, a[maxn], val[maxn];
vector<int>q[maxn];
map<int, int> p;
il int Random() {
return 1ll * rand() * rand() * rand();
}
signed main() {
srand(time(0));
int T = read();
while(T --) {
n = read();
rep(i, 1, n) a[i] = read(), q[a[i]].push_back(i), val[i] = 0;
rep(i, 1, n) {
int sum = 0;
for(re int j = 0; j < q[i].size(); ++ j) {
if(j == q[i].size() - 1) val[q[i][j]] = sum;
else sum ^= (val[q[i][j]] = Random());
}
q[i].clear();
}
int ans = 0, now = 0; p[0] = 1;
rep(i, 1, n) now ^= val[i], ans += p[now], ++ p[now];
rep(i, 1, n) now ^= val[i], p[now] = 0;
printf("%lld\n", ans);
}
return 0;
}
[JXOI2017]颜色的更多相关文章
- JXOI2017颜色 解题报告
JXOI2017颜色 首先记录每个位置上颜色在序列中上次出现的位置 开两颗线段树,第一棵维护区间最大值,实际上是维护当前必须被删去的颜色的位置的最大值,第二棵则是维护区间和 首先倒着扫一遍,对于当前颜 ...
- [JXOI2017]颜色 线段树求点对贡献
[JXOI2017]颜色 题目链接 https://www.luogu.org/problemnew/show/P4065 题目描述 可怜有一个长度为 n 的正整数序列 Ai,其中相同的正整数代表着相 ...
- [BZOJ5011][JXOI2017]颜色
5011: [Jx2017]颜色 Time Limit: 30 Sec Memory Limit: 512 MBSubmit: 84 Solved: 46[Submit][Status][Disc ...
- 洛谷P4065 [JXOI2017]颜色(线段树)
题意 题目链接 Sol 线段树板子题都做不出来,真是越来越菜了.. 根据题目描述,一个合法区间等价于在区间内的颜色没有在区间外出现过. 所以我们可以对于每个右端点,统计最长的左端点在哪里,刚开始以为这 ...
- JXOI2017颜色
题面 loj 分析 这道题非常妙啊 对于可保留区间[l, r] 枚举右端点r 考虑l的取值范围有两重约数 记颜色i出现的最右侧位置是\(max_i\) 最左侧位置是\(min_i\) r前最后一次出现 ...
- BZOJ5011 JXOI2017颜色(主席树)
相当于求满足在子段中出现的颜色只在该子段中出现的非空子段数量.这也就相当于其中出现的颜色最左出现的位置在左端点右侧,最右出现的位置在右端点左侧.那么若固定某个端点,仅考虑对该端点的限制,会有一段合法区 ...
- 【题解】JXOI2017颜色
一眼线段树...显然,我们可以考虑最后所留下的区间,那显然这个区间中应当不能存在任何与区间外相同的颜色.这里的转化也是很常用的,我们用 \(nxt[i]\) 表示与 \(i\) 颜色相同的下一个位置在 ...
- [JXOI2017]颜色 线段树扫描线 + 单调栈
---题面--- 题解: 首先题目要求删除一些颜色,换个说法就是要求保留一些颜色,那么观察到,如果我们设ll[i]和rr[i]分别表示颜色i出现的最左边的那个点和最右边的那个点,那么题目就是在要求我们 ...
- BZOJ5011 & 洛谷4065 & LOJ2275:[JXOI2017]颜色——题解
https://www.lydsy.com/JudgeOnline/problem.php?id=5011 https://www.luogu.org/problemnew/show/P4065 ht ...
- BZOJ5011 [JXOI2017]颜色 【线段树 + 主席树】
题目链接 BZOJ5011 题解 一定只有我这种智障会用这么奇怪的方法做这道题.. 由题我们知道最后剩余的一定是一个区间,而且区间内的颜色不存在于区间外 所以我们的目的就是为了找到这样的区间的数量 区 ...
随机推荐
- 通用32位CPU 常用寄存器及其作用
目录 32位CPU所含有的寄存器 数据寄存器 变址寄存器 指针寄存器 段寄存器 指令指针寄存器 标志寄存器 32位CPU所含有的寄存器 4个数据寄存器(EAX.EBX.ECX和EDX) 2个变址和指针 ...
- springboot整合druid、mybatis
目的: 1.springboot配置数据库连接池druid 测试druid中url监控 2.springboot整合mybatis 测试查删案例 3.springboot整合pagehelper sp ...
- sqlserver 转化函数
--查询系统当前时间select GETDATE() as date;------------------------- 0-14 ------------------select CONVERT(V ...
- Android SDK版本号 与 API Level 对应关系 201911
API是开发用的,所以API LEVEL可以认为是内部的:而SDK的版本提供了新特性给用户,是外部可见的. 可以查看以下网址以获取最新的对应关系: http://developer.android. ...
- oracle的LAST_DAY()函数
转自:https://blog.csdn.net/u012581453/article/details/53727936 LAST_DAY LAST_DAY函数返回指定日期对应月份的最后一天. 获取当 ...
- Hive笔记及配置
Hive 基于Hadoop的数据仓库工具: 将结构化的数据文件,映射为一张表,并提供类SQL查询功能: 本质:将HQL转化为MapReduce程序: Hive处理的数据存储在HDFS: Hive分析数 ...
- Flutter——FloatingActionButton组件(浮动按钮组件)
FloatingActionButton 简称 FAB ,可以实现浮动按钮,也可以实现类似闲鱼 app 的地步凸起导航. 属性名称 属性值 child 子视图,一般为 Icon,不推荐使用文字 ...
- 详解Linux磁盘管理与文件系统
磁盘基础 硬盘结构 物理结构 盘片:硬盘有多个盘片,每盘片 2 面. 磁头:每面一个磁头. 数据结构 扇区:磁盘上的每个磁道被等分为若干个弧段,这些弧段便是硬盘的扇区. 硬盘的第一个扇区,叫做引导扇区 ...
- JS函数篇【2】
什么是函数 函数的作用,可以写一次代码,然后反复地重用这个代码. <h3 onload="add2(1,2,3);add3(4,5,6)"></h3> &l ...
- Codeforces Round #499(Div2) C. Fly (二分精度)
http://codeforces.com/contest/1011/problem/C 题目 这是一道大水题! 仅以此题解作为我这个蒟蒻掉分的见证 #include<iostream> ...