链接:https://ac.nowcoder.com/acm/contest/372/D
来源:牛客网
题目描述
可能很多人要吐槽为什么标题不是“救救blabla”了。
怪人PM6喜欢数糖纸,不同的糖纸有不同的颜色,一共有 N 张糖纸,第 i 张糖纸颜色为 Ci ,它们的位置都是固定的。PM6喜欢五彩缤纷的糖纸,所以他不希望有重复的颜色。他有一次机会,可以收集任意一段连续区间内的糖纸。求出PM6最多能收集多少张糖纸。
输入描述:
第一行一个正整数 N ,表示共有 N 张糖纸。
第二行共有 N 个正整数,第 i 个正整数表示第 i 张糖纸的颜色 Ci
对于20%的数据:1<=N<=100
对于40%的数据:1<=N<=1000
对于100%的数据:1<=N<=1e6,0<=Ci<=1e9
输出描述:
一个整数表示PM6最多能收集多少张糖纸。
示例1
输入
复制
5
1 2 2 3 4
输出
复制
3
说明
PM6可以收集第3到第5张的糖纸,共有三张。
先看题解
题解代码:自己理解的代码待补~
//主要不知道怎么与离散化,离散化操作太多了
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<map>
#include<algorithm>
#define ll long long
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define inf (int)1e8
typedef unsigned long long ull;
using namespace std;
ll read(){
ll x=0,f=1;char c=getchar();
while(c<'0'||c>'9'){if(c=='-')f*=-1; c=getchar();}
while(c>='0'&&c<='9'){x=x*10+c-'0'; c=getchar();}
return f*x;
}
const int maxn=1e6+50;
struct Num{
int id;
int data;
}num[maxn];
bool cmp(const Num&a,const Num&b){
if(a.data<b.data)return 1;
return 0;
}
int c[maxn],N,cnt=0,top=0,stk[maxn],ans,max_ans=1,last[maxn];
int l,r;
bool via[maxn];
int main(){
N=read();
for(int i=1;i<=N;i++){
num[i].data=read();
num[i].id=i;
}
sort(num+1,num+N+1,cmp);
num[0].data=-1;
//离散化值得学习
for(int i=1;i<=N;i++){
if(num[i].data!=num[i-1].data)cnt++;
c[num[i].id]=cnt;
}//离散化的操作
//c数组就是离散过的原始数组
l=1;r=1;via[c[r]]=1;ans=1;last[c[r]]=r;//last就是c[r]上次出现的位置
while(l<=N&&r<N){
r++;//每次r++而l不变,这大概就是差分
if(via[c[r]]==0){
ans++;//当遍历的数没有出现过,答案加加
}
else {//出现过 last[c[r]]可以知道上次出现的位置,非常妙哦
for(int j=l;j<=last[c[r]];j++)via[c[j]]=0;//中间的不能用了
l=last[c[r]]+1;//上次的位置也不能用了,直接从上次的位置加1开始
ans=r-last[c[r]];
}
via[c[r]]=1;
max_ans=max(max_ans,ans);
last[c[r]]=r;//更新最新右端点的位置
}
printf("%d\n",max_ans);
return 0;
}
下面是另一个代码,感觉比上面那个好理解一些
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+10;
struct node
{
int v,id;
}a[N];
int n,last[N],c[N],vis[N];
bool cmp(node a,node b)
{
if(a.v==b.v) return a.id<b.id;
return a.v<b.v;
}
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i].v);
a[i].id=i;
}
sort(a+1,a+1+n,cmp);
int cnt=0;
a[0].v=-1;
for(int i=1;i<=n;i++)
{
if(a[i].v!=a[i-1].v) cnt++;
c[a[i].id]=cnt;
}
int l=1,r=1;
last[c[r]]=r;
int ans=1,sum=1;
while(l<=n&&r<=n)
{
r++;
if(vis[c[r]]==0)
{
last[c[r]]=r;
vis[c[r]]=1;
continue;
}
else
{
for(int i=l;i<=last[c[r]];i++) vis[c[i]]=0;
sum=r-l;
l=last[c[r]]+1;
ans=max(ans,sum);
last[c[r]]=r;
vis[c[r]]=1;
}
}
//printf("l:%d r:%d\n",l,r);
ans=max(ans,r-l);
cout<<ans<<endl;
}