记录一个菜逼的成长。。
题目链接
题目大意:
给你一个凸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;
}