Codeforces 755D:PolandBall and Polygon(思维+线段树)

http://codeforces.com/problemset/problem/755/D

题意:给出一个n正多边形,还有k,一开始从1出发,向第 1 + k 个点连一条边,然后以此类推,直到走完 n 次。对于每一步都要输出当前多边形中有多少个多边形。

思路:画了几幅图后发现规律:两个点相连,这条边多产生出来的多边形的数目等于跨越的边的数目+1,跨越边的数目是 x 和 x + k 中已经走过的点的数目。那么每次走一步,就求这段区间里面已经走过的点的数目,点的数目+1就是答案,区间查询单点更新,我用了线段树来维护。但是要注意 k > n / 2 的情况。因为 k > n / 2 的话,其实这时的 k 和 n - k 是一样的,就好比 n = 5, k = 2or3 的情况是一样的。因为这个情况WA了两次。

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <cmath>
 4 #include <cstdlib>
 5 #include <algorithm>
 6 #include <string>
 7 #include <iostream>
 8 #include <stack>
 9 #include <map>
10 #include <queue>
11 #include <set>
12 using namespace std;
13 typedef long long LL;
14 #define N 1000010
15 #define INF 0x3f3f3f3f
16 #define lson rt<<1, l, m
17 #define rson rt<<1|1, m+1, r
18 LL tree[N<<2];
19 vector<LL> ans;
20 
21 void pushup(int rt) { tree[rt] = tree[rt<<1] + tree[rt<<1|1]; }
22 
23 void update(int rt, int l, int r, int id) {
24     if(l == r && l == id) {
25         tree[rt]++;
26         return ;
27     }
28     int m = (l + r) >> 1;
29     if(id <= m) update(lson, id);
30     else update(rson, id);
31     pushup(rt);
32 }
33 
34 LL query(int rt, int l, int r, int L, int R) {
35     LL ans = 0;
36     if(L <= l && r <= R) return tree[rt];
37     int m = (l + r) >> 1;
38     if(L <= m) ans += query(lson, L, R);
39     if(m < R) ans += query(rson, L, R);
40     return ans;
41 }
42 
43 LL getsum(int l, int r, int n) {
44     LL ans = 0;
45     if(l > r) {
46         ans += query(1, 1, n, l, n);
47         ans += query(1, 1, n, 1, r);
48     } else {
49         ans += query(1, 1, n, l, r);
50     }
51     return ans;
52 }
53 
54 int main()
55 {
56     int n, k;
57     cin >> n >> k;
58     int now = 1 + k, pre;
59     if(k > n / 2) k = n - k;
60     LL res = 1;
61     for(int i = 1; i <= n; i++) {
62         pre = now; update(1, 1, n, pre);
63         now += k; if(now > n) now -= n;
64         res += getsum(pre, now, n) - 1;
65         ans.push_back(res);
66         update(1, 1, n, now);
67     }
68     for(int i = 0; i < n - 1; i++) printf("%I64d ", ans[i] + 1);
69     printf("%I64d
", ans[n-1]);
70     return 0;
71 }
原文地址:https://www.cnblogs.com/fightfordream/p/6291517.html