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\n", ans[n-1]); 70 return 0; 71 }