8VC Venture Cup 2017 — Elimination Round D PolandBall and Polygon (规律/树状数组)

题意:一个n边形,给定一个数字k,从顶点1开始每次隔k个点连一条线,每次输出这个n边形被分割成多少块区域。

思路:本次解题的关键是明确,每次新连一条线L,则增加的分割区域个数等于L穿过的线的条数+1。这样的话我们用树状数组维护,便于查询和更新信息。如果点u和点v之间连一条线,则a[u]++,a[u+k]++,然后线uv穿过的线的条数就是(u,v)之间点的个数。这是因为我们每连一条线,就在线段的两个端点+1,而如果uv之间的顶点存在这样的连线,那么一定会被uv所穿过。

代码one:

 1 #include <iostream>
 2 #include <queue>
 3 #include <stack>
 4 #include <cstdio>
 5 #include <vector>
 6 #include <map>
 7 #include <set>
 8 #include <bitset>
 9 #include <algorithm>
10 #include <cmath>
11 #include <cstring>
12 #include <cstdlib>
13 #include <string>
14 #include <sstream>
15 #include <time.h>
16 #define x first
17 #define y second
18 #define pb push_back
19 #define mp make_pair
20 #define lson l,m,rt*2
21 #define rson m+1,r,rt*2+1
22 #define mt(A,B) memset(A,B,sizeof(A))
23 #define mod 1000000007
24 using namespace std;
25 typedef long long LL;
26 const double PI = acos(-1);
27 const int N=1e6+10;
28 const int inf = 0x3f3f3f3f;
29 const LL INF=0x3f3f3f3f3f3f3f3fLL;
30 int n,k;
31 LL a[N],ans=1;
32 int lowbit(int x)
33 {
34     return x&(-x);
35 }
36 void update(int x)
37 {
38      while(x<=n)
39      {
40          a[x]++;
41          x+=lowbit(x);
42      }
43 }
44 LL sum(int x)
45 {
46     LL res=0;
47     while(x>0)
48     {
49         res+=a[x];
50         x-=lowbit(x);
51     }
52     return res;
53 }
54 int main()
55 {
56 #ifdef Local
57     freopen("data","r",stdin);
58 #endif
59     int u=1;
60     cin>>n>>k;
61     k=min(k,n-k);
62     mt(a,0);
63     for(int i=0;i<n;i++)
64     {
65         update(u);
66         if((u+k)>n)
67         {
68             update((u+k)%n);
69 
70             ans+=sum((u+k)%n-1)+sum(n)-sum(u)+1;
71             //cout<<1<<" "<<sum((u+k)%n-1)+sum(n)-sum(u)+1<<endl;
72             u=(u+k)%n;
73         }
74         else
75         {
76             update((u+k));
77             ans+=sum(u+k-1)-sum(u)+1;
78             //cout<<2<<" "<<sum(u+k-1)-sum(u)+1<<endl;
79             u+=k;
80         }
81         if(i==n-1)cout<<ans<<endl;
82         else cout<<ans<<" ";
83     }
84     return 0;
85 #ifdef Local
86     cerr << "time: " << (LL) clock() * 1000 / CLOCKS_PER_SEC << " ms" << endl;
87 #endif
88 }
View Code

代码two:

PS:这个是昨晚打的时候想出来的,运气很不错的歪打正着,特此纪念。比树状数组快,实现也简单。纯找规律。

 1 #include <iostream>
 2 #include <queue>
 3 #include <stack>
 4 #include <cstdio>
 5 #include <vector>
 6 #include <map>
 7 #include <set>
 8 #include <bitset>
 9 #include <algorithm>
10 #include <cmath>
11 #include <cstring>
12 #include <cstdlib>
13 #include <string>
14 #include <sstream>
15 #include <time.h>
16 #define x first
17 #define y second
18 #define pb push_back
19 #define mp make_pair
20 #define lson l,m,rt*2
21 #define rson m+1,r,rt*2+1
22 #define mt(A,B) memset(A,B,sizeof(A))
23 #define mod 1000000007
24 using namespace std;
25 typedef long long LL;
26 const double PI = acos(-1);
27 const int N=1e6+10;
28 const int inf = 0x3f3f3f3f;
29 const LL INF=0x3f3f3f3f3f3f3f3fLL;
30 LL a[N];
31 int main()
32 {
33 #ifdef Local
34     freopen("data","r",stdin);
35 #endif
36     LL n,k,cur=1,ans=1;
37     cin>>n>>k;
38     k=min(k,n-k);
39     for(LL i=1,j=1;i<=n;i++)
40     {
41         j+=k;
42         if(j>n)
43         {
44             cur++;
45             ans+=cur;
46             cur++;
47             j%=n;
48         }
49         else
50         {
51             ans+=cur;
52         }
53         if(i==n)cout<<ans-1<<endl;
54         else cout<<ans<<" ";
55     }
56 #ifdef Local
57     cerr << "time: " << (LL) clock() * 1000 / CLOCKS_PER_SEC << " ms" << endl;
58 #endif
59 }
View Code
原文地址:https://www.cnblogs.com/27sx/p/6291590.html