codeforces 755D PolandBall and Polygon(直线分割平面-树状数组优化查询)

来源:互联网 发布:java输入scanner 编辑:程序博客网 时间:2024/05/22 09:43
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.





题意:给出一个n边形,和距离k。 第一次连接 1和 k+1,第二次连接 k+1和 (k +1+k) % n,...依次进行,每次结束后输出n边形被分割成了几个区域。


题解: 直线分割平面。  新加入一条直线后的区域块数 = 原有的区域块数 + 与该直线相交直线的条数 +1

知道上面公式,就很容易解出这道题了,注意在查询与新加入直线相交直线的条数时,需要做log级别的查询,用树状数组查询更新一下就好了。

总结:QAQ~~~菜得抠脚啊,一眼看出来的做法,居然写了O(k)的查询维护,都没想到用bit维护更新。。。导致终测TLE。

代码如下:

#include <cstdio>#include <cstring>#include <algorithm>using namespace std;typedef long long LL;const int maxn = 1e6+10;int a[maxn],n,k;int sum(int x){int res = 0;while(x>0){res+=a[x];x -= x & -x;}return res;}void add(int x){while(x<=n){a[x]+=1;x += x & -x;}}int main(){while(scanf("%d%d",&n,&k)!=EOF){LL ans=1;int s=1,e;memset(a,0,sizeof(a));if(k>(n/2))//注意 k=n-k;for(int i=0;i<n;++i){e = (s+k)%n;if(e==0)e=n;if(s<e)ans += sum(e-1)-sum(s)+1;elseans += sum(n)-sum(s)+sum(e-1)+1;if(i!=n-1)printf("%lld ",ans);elseprintf("%lld\n",ans);add(s);add(e);s=e;}}return 0;} 


0 0