[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 题解 一定只有我这种智障会用这么奇怪的方法做这道题.. 由题我们知道最后剩余的一定是一个区间,而且区间内的颜色不存在于区间外 所以我们的目的就是为了找到这样的区间的数量 区 ...
随机推荐
- 网易自动化测试工具(airtest)的环境部署
airtest 环境配置: 1.安装Python2.7 及 Python3.6 版本(2个需要都安装) 2.配置python环境变量(AirtestIDE 需要在python2.x的环境下运行,所以尽 ...
- wannafly 挑战赛10 小H和游戏
题解: 先利用dfs找出各个节点之间的关系.然后利用一个sum[i][j] 数组 sum[i][0] 表示i这个节点收到影响的次数 sum[i][1]表示i这个节点的儿子们收到影响的次数 sum[i ...
- WPF打印控件内容
当我们想打印控件内容时,如一个Grid中的内容,可以用WPF中PrintDialog类的PrintVisual()方法来实现 界面如下: XAML代码如下 <Grid> <Grid. ...
- 解决Vs控制台程序出现NuGet\profile.ps1,因为在此系统上禁止运行脚本错误时或提示:“无法加载文件 \.nuget\packages\Microsoft.EntityFrameworkCore.Tools\1.1.0-preview4-final\tools\init.ps1,因为在此系统上禁止运行脚本”
1,打开Windows PowerShell 2.输入 set-executionpolicy remotesigned 即可执行脚本 如果执行命令失败的话重新选择Windows PowerShell ...
- POJ3368(Frequent values)--线段树
题目在这里 3368 Accepted 7312K 1829MS C++ 6936B 题意为给你一组数据,再给定一组区间,问你这个区间内出现次数最多的元素的次数是多少. 我还记得这题是学校校赛基础的题 ...
- EntityFramework进阶(四)- 实现批量新增
本系列原创博客代码已在EntityFramework6.0.0测试通过,转载请标明出处 我们可以结合Ado.Net的SqlBulkCopy实现SqlServer数据库的批量新增,其他类型的数据库的批量 ...
- Java虚拟机(五):JVM 类加载机制
一.JVM 类加载机制 JVM 类加载机制分为五个部分:加载,验证,准备,解析,初始化,下面我们就分别来看一下这五个过程. 1. 加载: 加载是类加载过程中的第一个阶段,这个阶段会在内存中生成一个代表 ...
- ipv4与ipv6 Inet4Address类和Inet6Address类
在设置本地IP地址的时候,一些人会疑惑IPv4与IPv6的区别是什么?下面由学习啦小编为你分享ipv4与ipv6的区别的相关内容,希望对大家有所帮助. ipv4与ipv6的区别 在windows 7以 ...
- Java Data JPA +hibernate 保存或者是查询遇到的坑
由于项目需求,接触了Java Data JPA +hibernate,它的调用方式是controller调用service,service有实现的接口serviceimpl,serviceimpl调用 ...
- Cknife流量分析
本文首发:https://<img src=1 onerror=\u006coc\u0061tion='j\x61v\x61script:\x61lert\x281\x29'>testde ...