您的位置:首页 > 编程语言 > Go语言

Codeforces 755-D. PolandBall and Polygon(树状数组+计算几何)

2017-01-18 15:12 232 查看
记录一个菜逼的成长。。

题目链接

题目大意:

给你一个凸n边形。从1开始,将点与接下来的第k个点连条线,然后从第k个点开始重复操作,每次操作输出凸边形有多少块区域。不会有三条线交于一点的情况。

我们需要知道每次连线相交了多少条线。

假设现在在x点,那么只需要知道x+1,…,x+k-1和x-k+1,…,x-1有多少条线是以这些点为起点的。因为如果是以这些点为起点的线,那么x’+k肯定会超过x或x+k。

但是k必须满足min(k,n-k)

因为如果k超过了n/2那么有些线段会被计算两次。

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
#define pb push_back
#define mp make_pair
#define lowbit(x) (x)&(-x)
const int INF = 0x3f3f3f3f;
const int maxn = 1000000 + 10;
//tot是用来统计目前为止有多少条线段,也等于getsum(n)
int c[maxn],n,k,tot;
void modify(int pos,int t)
{
for( int i = pos; i <= n; i += lowbit(i))
c[i] += t;
tot += t;
}
int getsum(int pos)
{
int ret = 0;
for( int i = pos; i >= 1; i -= lowbit(i))
ret += c[i];
return ret;
}
int query(int x)
{
if(x >= n)return getsum(x-n) + tot;
else if(x < 0)return getsum(x+n) - tot;
return getsum(x);
}
int main()
{
while(~scanf("%d%d",&n,&k)){
k = min(k,n-k);
LL ans = 1;int x = 1;
for( int i = 1; i <= n;i++ ){
int t = query(x+k-1) - query(x-k);
ans += t + 1;
modify(x,1);
x = (x + k - 1) % n + 1;
printf("%lld ",ans);
}
puts("");
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息