困困,今天勉强写个补题的博客吧!因为发现思考一遍距离可以写出来仍然有很大一个差距……咳咳咳,就是我太懒才拖到了现在!!
(1)Elephant And Array(枚举)
题目链接: CodeForces - 221D
题意:给你一个序列,给定一个区间,问在这个区间中有哪些数字出现了它的数值那么多次。
思路(莫队不会呐!!):用数组存储b[数值]=出现次数,注意如果只有n个数,那么如果出现其数值大于n的m,就它绝对不可能出现m次!(最多n个数哇)。
第一次循环,先找到出现次数多于数值本身的(例如b[4]=6),以这个数值为基础,再遍历一次序列,标记出在每一个位置这个数值出现的次数。遍历完一遍之后,对于每个问题,看看这个数字是否符合要求(利用前缀和,比如在l处已经出现了2次,在r处总计已经出现了5次,那么在[l,r]中,就出现了5-2=3次,如果恰好等于此时的数字i=4,那么符合要求),ans[j]++;(j是循环的题目)。
代码:
#include<iostream>
#include<cstring>
using namespace std;
int n,m,ans[10000],a[10000],b[10000],sum[10000];//忘了该开多大空间
int l[10000],r[10000];
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++)
{
cin>>a[i];
if(a[i]<=n)
{
b[a[i]]++;
}
}
for(int i=1;i<=m;i++)
cin>>l[i]>>r[i];
for(int i=1;i<=n;i++)
{
if(b[i]>=i)
{
for(int j=1;j<=n;j++)
{
if(a[j]==i)
sum[j]=sum[j-1]+1;
else
sum[j]=sum[j-1];
}
for(int j=1;j<=m;j++)
{
if(sum[r[j]]-sum[l[j]-1]==i)//l这部分的减1可能会忘掉,不减1的话最左边如果也有一个数字就不会被算上
ans[j]++;
}
}
}
for(int i=1;i<=m;i++)
{
cout<<ans[i]<<endl;
}
}
(2)Array(枚举)
题目链接:CodeForces - 224B
题意:给定一个序列a,求一个序列,使这个序列中恰好有k个不同的数,数列可以不是最短的(我喜欢最短!!)。
思路:枚举,从前往后找,找到k个不同的元素,标记这里的位置,然后从这里往前,也是找k个不同的元素(第一遍最左边要是第一个元素相同了好几个,就可以通过这里来消去相同的)。
代码:
#include<iostream>
#include<cstring>
#include<set>
using namespace std;
int main()
{
int n,k,a[10000];
int be,en;
int flag=0,flag2=0;
set<int> s;
cin>>n>>k;
for(int i=1;i<=n;i++) cin>>a[i];
for(int i=1;i<=n;i++)
{
s.insert(a[i]);
if(s.size()==k)
{
flag=1;
en=i;
break;
}
}
s.clear();
for(int j=en;j>=1;j--)
{
s.insert(a[j]);
if(s.size()==k)
{
flag2=1;
be=j;
break;
}
}
if(flag==1&&flag2==1)
cout<<be<<" "<<en<<endl;
else cout<<"-1 -1"<<endl;
return 0;
}