题目链接:点这里
参考别人的代码写出来的吧,想到了枚举,不知道怎么维护,GG
题意:给你一个长度为n的数组a,我们称一个连续的序列为数组a的子序列。
我们叫该子序列为k-good如果该子序列包含不超过k个不同的数。找到最长的k-good。
数据范围:1<=k<=n<=500000, a[i]<=1000000
题解:
很容易想到枚举左端点,找符合条件编号最大的右端点。
假设当前找到符合条件的最大区间为[Li Ri],接下来我们要找Li+1为起点的最长符合条件的区间。
Li+1开头的初始区间就是[Li+1,Ri],与之前的[Li,Ri]就少了个Li,我们只要利用统计的方法就能通过[Li,Ri]推到出[Li+1,Ri]。
然后我们在让Ri++,直到不符合条件为止。以此类推就能得到答案。
代码:
#include<cstdio> #include<cstring> #include<iostream> #include<sstream> #include<algorithm> #include<vector> #include<bitset> #include<set> #include<queue> #include<stack> #include<map> #include<cstdlib> #include<cmath> #define PI 2*asin(1.0) #define LL long long #define pb push_back #define pa pair<int,int> #define clr(a,b) memset(a,b,sizeof(a)) #define lson lr<<1,l,mid #define rson lr<<1|1,mid+1,r #define bug(x) printf("%d++++++++++++++++++++%d\n",x,x) #define key_value ch[ch[root][1]][0] const LL MOD = 1000000000+7; const int N = 5e5+15; const int maxn = 1e6+1000; const int letter = 130; const int INF = 1e17; const double pi=acos(-1.0); const double eps=1e-8; using namespace std; inline int read() { int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } int n,k,a[N]; int vis[maxn]; int main(){ scanf("%d%d",&n,&k); for(int i=1;i<=n;i++) scanf("%d",a+i); int l=1,r=1; vis[a[1]]=1; int cnt=1,pos=2; for(int i=1;i<=n;i++){///l while(pos<=n&&cnt<=k){ /// pos r ++vis[a[pos]]; if(vis[a[pos]]==1)cnt++; if(cnt<=k)pos++; } if(r-l<pos-1-i) l=i,r=pos-1; --vis[a[i]]; if(vis[a[i]]==0) cnt--,pos++; } printf("%d %d\n",l,r); return 0; }