博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
多校2019 Contest 2 hdu6602 Longest Subarray
阅读量:4569 次
发布时间:2019-06-08

本文共 2136 字,大约阅读时间需要 7 分钟。

给定一个值域在 \([1,\ m]\) 的长度为 \(n\) 的正整数序列 \(a_i\) ,求出最长的子序列满足:\[\forall x\in[1,\ m],\ \displaystyle\sum_{i=l}^r[a_i=x]=0,\ or \displaystyle\sum_{i=l}^r[a_i=x]\ge k\]

\(n,\ m,\ k\leq10^5\)

数据结构


考虑对于每个右端点 \(i\) ,不合法的区间为 \([i\) 的上 \(k-1\) 次出现的位置 \(+1\) \(,\ i]\) 。考虑对于这一段区间打 \(+1\) 标记,询问合法的区间即为找到最小的为 \(0\) 的位置,可以用线段树维护。由于只需要考虑不同的数的贡献,因此每次修改需要将上一次修改撤销。

时间复杂度 \(O(n\log n)\)

代码

#include 
using namespace std;const int maxn = 1e5 + 10;int n, m, k, a[maxn], pos[maxn], pre[maxn], lst[maxn];vector
vec[maxn];#define mid ((l + r) >> 1)#define lson k << 1, l, mid#define rson k << 1 | 1, mid + 1, rint tag[maxn << 2], val[maxn << 2];inline void pushtag(int k, int x) { tag[k] += x, val[k] += x;}inline void pushdown(int k) { int &x = tag[k]; if (x) { pushtag(k << 1, x); pushtag(k << 1 | 1, x); x = 0; }}inline void maintain(int k) { val[k] = min(val[k << 1], val[k << 1 | 1]);}void upd(int k, int l, int r, int ql, int qr, int x) { if (ql <= l && r <= qr) { pushtag(k, x); return; } pushdown(k); if (ql <= mid) upd(lson, ql, qr, x); if (qr > mid) upd(rson, ql, qr, x); maintain(k);}int query(int k, int l, int r) { if (l == r) return l; pushdown(k); assert(val[k] >= 0); if (val[k]) return n + 1; return val[k << 1] ? query(rson) : query(lson);}#undef mid#undef lson#undef rsoninline void add(int x, int v) { if (x) upd(1, 1, n, lst[x] + 1, x, v);}void solve() { memset(pos, 0, (n + 1) << 2); memset(lst, 0, (n + 1) << 2); memset(tag, 0, (n + 1) << 4); memset(val, 0, (n + 1) << 4); for (int i = 1; i <= m; i++) { vec[i].clear(); } for (int i = 1; i <= n; i++) { scanf("%d", a + i); vec[a[i]].push_back(i); pre[i] = pos[a[i]], pos[a[i]] = i; } for (int i = 1; i <= m; i++) { int sz = vec[i].size(); for (int j = k - 1; j < sz; j++) { lst[vec[i][j]] = vec[i][j - k + 1]; } } int ans = 0; for (int i = 1; i <= n; i++) { add(pre[i], -1), add(i, 1); ans = max(ans, i - query(1, 1, n) + 1); } printf("%d\n", ans);}int main() { while (~scanf("%d %d %d", &n, &m, &k)) { solve(); } return 0;}

转载于:https://www.cnblogs.com/Juanzhang/p/11312261.html

你可能感兴趣的文章
使用squid架设自己的代理server
查看>>
136. Single Number; 137. Single Number II;260. Single Number III; 287. Find the Duplicate Number
查看>>
Android游戏可能遇到的3个问题及解决方案
查看>>
浅谈innerHTML,innerText与outerHTML,outerText的区别
查看>>
shell中的declare命令
查看>>
SQL Server— 存在检测、建库、 建表、约束、外键、级联删除
查看>>
堆——数据结构
查看>>
CSS3特效----制作立体导航栏菜单
查看>>
性能测试应用领域
查看>>
JAVA 主要特性
查看>>
DataBase First创建数据库
查看>>
NSString和NSMutableNSString的基本用法
查看>>
Selenium_WebDriver_定位元素
查看>>
spring 的redis操作类RedisTemplate
查看>>
第三篇——软件工程之结构化设计方法
查看>>
文件上传和下载
查看>>
存储过程/存储函数
查看>>
C++ && C# 函数的递归调用
查看>>
Json-lib 进行java与json字符串转换之一
查看>>
c++基础知识学习-----数据程序的储存、表示形式和基本运算
查看>>