Codeforces755D PolandBall and Polygan

题目戳这里

我们只需要计算每增加一条线后穿过了几条已有的线即可。为了方便,我们令\(K \le N/2\),并且给每条线一个方向,即\(x\)\((x+K) \; mod \; N\)。然后我们假设现在我们正在链接\(a\)\((a+K) \; mod \; N\)这条线,于是他穿过的线就是从\((a-K,a+k)\)(模\(K\)意义下)$这段区间中点射出边的数目,拿个树状数组维护一下即可。

#include<cstdio>
#include<cstdlib>
using namespace std;

typedef long long ll;
#define lowbit(a) (a&-a)
const int maxn = 1000010;
int N,K,now,tree[maxn]; ll ans = 1LL;

inline void ins(int a) { for (++a;a <= N;a += lowbit(a)) ++tree[a]; }
inline ll calc(int a) { int ret = 0; for (++a;a;a -= lowbit(a)) ret += tree[a]; return (ll)ret; }

int main()
{
	freopen("755D.in","r",stdin);
	freopen("755D.out","w",stdout);
	scanf("%d %d",&N,&K); if (N - K < K) K = N-K;
	do
	{
		if (now+K-1<N)
		{
			ans += calc(now+K-1)-calc(now);
			if (now - K < 0) ans += calc(now-1)+calc(N-1)-calc(now-K+N);
			else ans += calc(now-1)-calc(now-K);
		}
		else
		{
			ans += calc(N-1)-calc(now)+calc(now+K-1-N);
			if (now - K < 0) ans += calc(now-1)+calc(N-1)-calc(now-K+N);
			else ans += calc(now-1)-calc(now-K);
		}
		ins(now); now += K; if (now >= N) now -= N;
		printf("%lld ",++ans);
	}
	while (now);
	fclose(stdin); fclose(stdout);
	return 0;
}
posted @ 2017-01-24 00:31  lmxyy  阅读(255)  评论(0编辑  收藏  举报