[LGOJ] 题解 P4889 【kls与flag】

本文详细解析了洛谷月赛加赛中的一道题目——竹竿问题,介绍了如何利用STL的map来统计竹竿顶点重合情况,通过遍历map并应用等差数列求和公式,高效计算竹竿间所有可能的接触次数。
洛谷月赛加赛的题

点击跳题

点击跳洛谷blog

点个赞,谢谢 \color{red}\text{点个赞,谢谢} 点个赞,谢谢

思路大概如下(使用STL的map)

  • 定义函数 f ( x ) f(x) f(x),代表 1 + 2 + . . . + x − 1 1+2+...+x-1 1+2+...+x1的和

  1. 输入竹竿高度 k k k , m a p [ k ] + + map[k]++ map[k]++,所以 m a p [ k ] map[k] map[k]表示k处有几根竹竿顶重合
  2. 遍历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+...+x1)

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;
}


评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值