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;
}
原文地址:https://www.cnblogs.com/mmlz/p/6345594.html