赞
踩
题意是这样的,我们给出了N个数组成的这个长长的区间,我们要求的是这段区间的最大连续,保证这段连续的区间内的出现的每个数的次数都"≥K",或者就是没有出现过。题目中所给出的所有的ai都≤C。
那么,怎么想呢(真的好难想啊,看了好多blog之后才大致理解了他们的意思所在)。
我们知道,如果K==1的时候,整个区间都是能选的,所以这时候是一定为N的答案。
但是,当K≥2的时候,岂不是就不好处理了?确实啊……
我们这样去考虑,现在假如选出一个点,那么它肯定是不符合的,但是呢,如果第K次出现这个数的时候,是不是这段区间就是符合的了。
再看,我们放进去一个数u,先不管它放进去的合法性,我们把它放进去,那么肯定它的上一次出现的位置的后一位(pos + 1)一直到它的前一位(i - 1)之间的区间的值如果要算进第i位这个区间内的话,如果我们要把(pos + 1)位一直连到第i位的话,就会使得这段区间一定会多出一个不合法的项,就是u这个值;
那么,再看看它的合法性,如果它是合法的话呢,我们是不是要找到K个u,那么也就是我们需要找到前面的第K次出现的u的位置。那么,我们就可以给第K次之前的第K+1次的后面一位到目前这段区间上的区间,我们如果选择的话,合法性就是会多一个元素。
然后,我们只是需要找到之前出现的C个元素都合法的最早出现的位置就可以了。
- #include <iostream>
- #include <cstdio>
- #include <cmath>
- #include <string>
- #include <cstring>
- #include <algorithm>
- #include <limits>
- #include <vector>
- #include <stack>
- #include <queue>
- #include <set>
- #include <map>
- #define lowbit(x) ( x&(-x) )
- #define pi 3.141592653589793
- #define e 2.718281828459045
- #define INF 0x3f3f3f3f
- #define HalF (l + r)>>1
- #define lsn rt<<1
- #define rsn rt<<1|1
- #define Lson lsn, l, mid
- #define Rson rsn, mid+1, r
- #define QL Lson, ql, qr
- #define QR Rson, ql, qr
- #define myself rt, l, r
- using namespace std;
- typedef unsigned long long ull;
- typedef long long ll;
- const int maxN = 1e5 + 7;
- int N, C, K, lazy[maxN<<2];
- vector<int> vt[maxN];
- struct node
- {
- int val, id; //用来维护这段区间的合法的数的个数
- node(int a=0, int b=0):id(a), val(b) {}
- }tree[maxN<<2];
- inline void buildTree(int rt, int l, int r)
- {
- tree[rt] = node(l, C - 1); lazy[rt] = 0;
- if(l == r) return;
- int mid = HalF;
- buildTree(Lson); buildTree(Rson);
- }
- inline void pushdown(int rt, int l, int r)
- {
- if(lazy[rt])
- {
- tree[lsn].val += lazy[rt]; tree[rsn].val += lazy[rt];
- lazy[lsn] += lazy[rt]; lazy[rsn] += lazy[rt];
- lazy[rt] = 0;
- }
- }
- inline void pushup(int rt, int l, int r)
- {
- if(tree[lsn].val >= tree[rsn].val) tree[rt] = tree[lsn];
- else tree[rt] = tree[rsn];
- }
- inline void update(int rt, int l, int r, int ql, int qr, int val)
- {
- if(ql > qr) return;
- if(ql <= l && qr >= r)
- {
- tree[rt].val += val;
- lazy[rt] += val;
- return;
- }
- pushdown(myself);
- int mid = HalF;
- if(qr <= mid) update(QL, val);
- else if(ql > mid) update(QR, val);
- else { update(QL, val); update(QR, val); }
- pushup(myself);
- }
- inline node query(int rt, int l, int r, int ql, int qr)
- {
- if(tree[rt].val < C) return node(0, 0);
- if(ql <= l && qr >= r) return tree[rt];
- pushdown(myself);
- int mid = HalF;
- if(qr <= mid) return query(QL);
- else if(ql > mid) return query(QR);
- else
- {
- node TL = query(QL), TR = query(QR);
- if(TL.val >= TR.val) return TL;
- else return TR;
- }
- }
- inline void init()
- {
- for(int i=1; i<=C; i++) { vt[i].clear(); vt[i].push_back(0); }
- }
- int main()
- {
- while(scanf("%d%d%d", &N, &C, &K) != EOF)
- {
- init();
- int ans = 0;
- buildTree(1, 1, N); //每个点出初始假定合法区间的数目是C-1
- for(int i=1, u; i<=N; i++)
- {
- scanf("%d", &u);
- if(K == 1) continue; //因为K==1的时候无论怎样的,答案都是N
- update(1, 1, N, vt[u].back() + 1, i - 1, -1); //在K大于1的时候,我们得去考虑,这段区间不合法的数量就变多了一个
- vt[u].push_back(i);
- int pos = (int)vt[u].size() - K - 1; //如果"≥0"说明我们确实能找到u合法的一段区间,在这段区间内,我们可以保证u的合法性
- if(pos >= 0) update(1, 1, N, vt[u][pos] + 1, vt[u][pos + 1], 1); //说明是有这样的点的,那么我们就是可以去给这段合法区间加上之前减去的“1”
- node tmp = query(1, 1, N, 1, i);
- int j = (tmp.val >= C ? tmp.id : 0); //找到以i为右端点的最远到达的合法区间的点
- if(!j) continue;
- ans = max(ans, i - j + 1);
- }
- if(K == 1) ans = N;
- printf("%d\n", ans);
- }
- return 0;
- }
- /*
- 7 4 2
- 2 1 4 1 4 3 2
- ans: 4
- */
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。