codeforces 8VC Venture Cup 2017 - Elimination Round D PolandBall and Polygon

本文介绍了一种算法,用于计算随着特定红线条段的添加,凸多边形内部区域数量的变化过程。通过使用树状数组来高效地更新和查询边界上的连接情况,实现了对每个操作后多边形分区数量的准确计算。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

D. PolandBall and Polygon
time limit per test
4 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

PolandBall has such a convex polygon with n veritces that no three of its diagonals intersect at the same point. PolandBall decided to improve it and draw some red segments.

He chose a number k such that gcd(n, k) = 1. Vertices of the polygon are numbered from 1 to n in a clockwise way. PolandBall repeats the following process n times, starting from the vertex 1:

Assume you've ended last operation in vertex x (consider x = 1 if it is the first operation). Draw a new segment from vertex x to k-th next vertex in clockwise direction. This is a vertexx + k or x + k - n depending on which of these is a valid index of polygon's vertex.

Your task is to calculate number of polygon's sections after each drawing. A section is a clear area inside the polygon bounded with drawn diagonals or the polygon's sides.

Input

There are only two numbers in the input: n and k (5 ≤ n ≤ 1062 ≤ k ≤ n - 2gcd(n, k) = 1).

Output

You should print n values separated by spaces. The i-th value should represent number of polygon's sections after drawing first i lines.

Examples
input
5 2
output
2 3 5 8 11 
input
10 3
output
2 3 4 6 9 12 16 21 26 31 
Note

The greatest common divisor (gcd) of two integers a and b is the largest positive integer that divides both a and b without a remainder.

For the first sample testcase, you should output "2 3 5 8 11". Pictures below correspond to situations after drawing lines.

题意如图,因为保证了gcd(n,k)==1,所以肯定不会出现重边的情况,所以每次增加的区域个数,其实也就是这条线起点终点两点之间的所有点上的已有的边之和再加一,

例如这一次起点是1,终点是3,增加的区域数也就是2顶点上连的边个数加一,直接暴力求之间所有边的和肯定会t,所以用树状数组维护,模拟求和


但最后wa在了test6上。。。


没想出来为什么,看了题解,发现好智障

当k>n/2时,起点和终点的跨过区域就是反向的,令k=n-k即可(可以联想一下圆,扇形圆心角大于180度时候的情况)

#include<stdio.h>
int bit[1000006],n,k;
int sum(int i)
{
	int s=0;
	while(i>0)
	{
		s+=bit[i];
		i-=i&-i;
	}
	return s;
}
void add(int i,int x)
{
	while(i<=n)
	{
		bit[i]+=x;
		i+=i&-i;
	}
	return ;
}
int main()
{
	int x,be,ne,j,i;
	long long int ans;
	scanf("%d %d",&n,&k);
	if(k>(n/2))
	k=n-k;
	j=n;
	be=1;
	ans=1;
	while(j--)
	{
		ne=be+k;
		if(ne>n)
		{
			ne-=n;
			ans+=(sum(n)-sum(be));
			ans+=sum(ne-1);
			ans++;	
		}
		else
		{
			ans+=(sum(ne-1)-sum(be)+1);
		}
		add(be,1);
		add(ne,1);
		be=ne;
		printf("%lld ",ans);
	}
	printf("\n");
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值