题目链接:https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=3892
题意:给出有n个数的序列,进行m次询问,每次询问给出一个区间[l,r],问区间中是否有重复的数
思路:把整个序列进行一次预处理,求出与第i个数相等且排在它前面的数保存在pr[i],最后询问时枚举区间每一个数,比较pr[i]与l的大小,题目给的时间比较宽松,所以水过去了,更好的做法是利用线段树,或者pr[i]标记离第i个数最近且有重复出现的数字的位置
下面是我自己的代码(因为我要用数组记录的原因进行了离散化)
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
struct Node
{
int val,pos;
}temp[1000030],s[1000030];
bool cmp(Node p,Node q)
{
return p.val<q.val;
}
int vis[1000030],pr[1000030];
int main()
{
int n,m;
while (scanf("%d%d",&n,&m)!=EOF)
{
if (n==0 && m==0) break;
memset(vis,-1,sizeof(vis));
memset(pr,-1,sizeof(pr));
for (int i=0;i<n;i++)
{
scanf("%d",&temp[i].val);
temp[i].pos=i;
}
sort(temp,temp+n,cmp);
s[temp[0].pos].val=0;
s[temp[0].pos].pos=temp[0].val;
int tem=0;
for (int i=1;i<n;i++)
{
if (temp[i].val!=temp[i-1].val)
{
tem++;
s[temp[i].pos].val=tem;
s[temp[i].pos].pos=temp[i].val;
}
else
{
s[temp[i].pos].val=tem;
s[temp[i].pos].pos=temp[i].val;
}
}
// for (int i=0;i<n;i++)
// {
// cout<<":"<<s[i].val<<endl;
// }
for (int i=0;i<n;i++)
{
if (vis[s[i].val]!=-1)
{
pr[i]=vis[s[i].val];
vis[s[i].val]=i;
}
else
{
vis[s[i].val]=i;
}
}
for (int i=0;i<m;i++)
{
int l,r,flag=1;
scanf("%d%d",&l,&r);
for (int j=l-1;j<r;j++)
{
if (pr[j]>=l-1)
{
cout<<s[j].pos<<endl;
flag=0;
break;
}
}
if (flag==1) cout<<"OK"<<endl;
}
cout<<endl;
}
}