洛谷月赛加赛的题
点个赞,谢谢 \color{red}\text{点个赞,谢谢} 点个赞,谢谢
思路大概如下(使用STL的map)
- 定义函数 f ( x ) f(x) f(x),代表 1 + 2 + . . . + x − 1 1+2+...+x-1 1+2+...+x−1的和
- 输入竹竿高度 k k k , m a p [ k ] + + map[k]++ map[k]++,所以 m a p [ k ] map[k] map[k]表示k处有几根竹竿顶重合
- 遍历map,对于 a n s = a n s + f ( i 的值 ) ans=ans+f(i\text{的值}) ans=ans+f(i的值)
对于 f ( x ) f(x) f(x),不难理解,一个点有x个竿重合,两两配对,显然是 ( 1 + 2 + . . . + x − 1 ) (1+2+...+x-1) (1+2+...+x−1)次
map用来统计哪些点被几根竹竿覆盖,(如数据较小可以用数组)
话不多说,上代码!
#include<bits/stdc++.h>
using namespace std;
long long n,m; //注意开long long,否则30分
map<long long,long long> mmp; //定义map
long long val(long long x) //f(x)
{
if(x<2) return 0; //竹竿不能盖在一起
return x*(x-1)/2; //等差数列公式
}
int main()
{
cin>>n>>m; //输入
for(long long i=1;i<=n;i++)
{
long long k;
scanf("%lld",&k);
mmp[k+i]++; //向右倒竹竿顶落在的点
mmp[i-k]++; //向左倒竹竿顶落在的点
}
long long ans=0; //计数器
//遍历map
for(map<long long,long long>::iterator i=mmp.begin();i!=mmp.end();i++)
{
//i->second表示该点有(i->second)个竿重合
ans+=val(i->second);//统计
}
cout<<ans;//输出
return 0;
}
本文详细解析了洛谷月赛加赛中的一道题目——竹竿问题,介绍了如何利用STL的map来统计竹竿顶点重合情况,通过遍历map并应用等差数列求和公式,高效计算竹竿间所有可能的接触次数。

被折叠的 条评论
为什么被折叠?



