• 2017中国大学生程序设计竞赛-哈尔滨站 Solution


    A - Palindrome

    题意:给出一个字符串,找出其中有多少个子串满足one-half-palindromic 的定义

    思路:其实就是找一个i, j  使得 以i为中轴的回文串长度和以j为中轴的回文串长度都大于j - i + 1

    先Manacher 预处理出以每个字符为中轴的最长回文串长度,然后用树状数组维护j ,枚举i

     1 #include<bits/stdc++.h>
     2 
     3 using namespace std;
     4 
     5 typedef long long ll;
     6 const int maxn = 5e5 + 10;
     7 
     8 int l;
     9 char Ma[maxn << 1];
    10 int Mp[maxn << 1];
    11 
    12 inline void Manacher(char s[], int len)
    13 {
    14     l = 0;
    15     Ma[l++] = '$';
    16     Ma[l++] = '#';
    17     for(int i = 0; i < len; ++i)
    18     {
    19         Ma[l++] = s[i];
    20         Ma[l++] = '#';
    21     }
    22     Ma[l] = 0;
    23     int mx = 0, id = 0;
    24     for(int i = 0; i < l; ++i)
    25     {
    26         Mp[i] = mx > i ? min(Mp[2 * id - i], mx - i) : 1;
    27         while(Ma[i + Mp[i]] == Ma[i - Mp[i]]) Mp[i]++;
    28         if(i + Mp[i] > mx)
    29         {
    30             mx = i + Mp[i];
    31             id = i;
    32         }
    33     }
    34 }
    35 
    36 int cnt[maxn << 1];
    37 char str[maxn];
    38 int a[maxn];
    39 int len;
    40 
    41 vector <int> vv[maxn];
    42 
    43 inline int lowbit(int x)
    44 {
    45     return x & (-x);
    46 }
    47 
    48 inline void update(int x, int val)
    49 {
    50     for (int i = x; i <= len; i += lowbit(i))
    51         a[i] += val;
    52 }
    53 
    54 inline int query(int x)
    55 {
    56     int res = 0;
    57     for (int i = x; i > 0; i -= lowbit(i))
    58         res += a[i];
    59     return res;
    60 }
    61 
    62 int main()
    63 {
    64     int t;
    65     scanf("%d", &t);
    66     while(t--)
    67     {
    68         memset(a, 0, sizeof a);
    69         scanf("%s", str);
    70         len = strlen(str);
    71         Manacher(str, len);
    72         ll ans = 0;
    73         int pos = 1;
    74         for(int i = 2 ; i < l; i += 2)
    75         {
    76             cnt[pos]= Mp[i] / 2 - 1;
    77             vv[pos - cnt[pos]].push_back(pos);
    78             pos++;
    79         }
    80         for(int i = 1; i <= pos; ++i)
    81         {
    82             for (auto it : vv[i])
    83             {
    84                 update(it, 1);
    85             }
    86             vv[i].clear();
    87             ans += query(i + cnt[i]) - query(i);
    88 //            cout << ans << endl;
    89         }
    90         printf("%lld
    ",ans);
    91     }
    92     return 0;
    93 }
    View Code

    B - K-th Number

    题意:给出n个数,把这n个数中长度>= k 的区间中的第k小的数放到数组b中,最后求出数组b中的第m大的数

    思路:二分答案,然后双指针法判断是否正确,因为存在这样一个性质,假如一个长度>=k的区间里面的第k小的数 >= ans

    那么 之后如果加入的数大于它,那么没有影响,如果小于它,要被计数

     1 #include<bits/stdc++.h>
     2 
     3 using namespace std;
     4 
     5 typedef long long ll;
     6 const int maxn = 1e5 + 10;
     7 
     8 int n, k ;
     9 ll m;
    10 int arr[maxn];
    11 int brr[maxn];
    12 
    13 inline bool check(int mid)
    14 {
    15     ll tot = 0;
    16     ll res = 0;
    17     for(int i = 1, j = 0; i <= n; ++i)
    18     {
    19         while(j <= n && res < k)
    20         {
    21             if(arr[++j] >= mid) ++res;
    22         }
    23         if(res >= k) tot += n - j + 1;
    24         if(arr[i] >= mid) res--;
    25     }
    26     return tot >= m;
    27 }
    28 
    29 int main()
    30 {
    31     int t;
    32     scanf("%d", &t);
    33     while(t--)
    34     {
    35         scanf("%d %d %lld", &n, &k, &m);
    36         for(int i = 1; i <= n; ++i)
    37         {
    38             scanf("%d", arr + i);
    39             brr[i] = arr[i];
    40         }
    41         sort(brr + 1, brr + 1 + n);
    42         int l = 1;
    43         int r = n;
    44         int ans = 0;
    45         while(r - l >= 0)
    46         {
    47             int mid = (l + r) >> 1;
    48             if(check(brr[mid]))
    49             {
    50                 ans = mid;
    51                 l = mid + 1;
    52             }
    53             else
    54             {
    55                 r = mid - 1;
    56             }
    57         }
    58         printf("%d
    ",brr[ans]);
    59     }
    60     return 0;
    61 }
    View Code

    C - Confliction

    留坑。

    D - X-Men

    题意:有若干个X-Man  他们要汇合,直到所有Xman的距离都小于等于1的时候,他们就停止行动,一个小时行进一个单位长度,求他们期望的行进时间

    思路:因为给的是一棵树,实际上就是最远的两个X-man 的距离 / 2

      1 #include <bits/stdc++.h>
      2 using namespace std;
      3 
      4 #define N 1010
      5 
      6 struct Edge
      7 {
      8     int to, nx;
      9     inline Edge() {}
     10     inline Edge(int to, int nx) : to(to), nx(nx) {}
     11 }edge[N << 1];
     12 
     13 int t, n, m;
     14 int head[N], pos;
     15 bool vis[N];
     16 
     17 inline void Init()
     18 {
     19     memset(vis, false, sizeof vis);
     20     memset(head, -1, sizeof head);
     21     pos = 0;
     22 }
     23 
     24 inline void addedge(int u, int v)
     25 {
     26     edge[++pos] = Edge(v, head[u]); head[u] = pos;
     27     edge[++pos] = Edge(u, head[v]); head[v] = pos;
     28 }
     29 
     30 int rmq[N << 1];
     31 int F[N << 1];
     32 int P[N], deep[N];
     33 int cnt;
     34 
     35 struct ST
     36 {
     37     int mm[N << 1];
     38     int dp[N << 1][20];
     39     inline void init(int n)
     40     {
     41         mm[0] = -1; 
     42         for (int i = 1; i <= n; ++i)
     43         {
     44             mm[i] = ((i & (i - 1)) == 0) ? mm[i - 1] + 1 : mm[i - 1];
     45             dp[i][0] = i;
     46         }
     47         for (int j = 1; j <= mm[n]; ++j)
     48             for (int i = 1; i + (1 << j) - 1 <= n; ++i)
     49                 dp[i][j] = rmq[dp[i][j - 1]] < rmq[dp[i + (1 << (j - 1))][j - 1]] ? dp[i][j - 1] : dp[i + (1 << (j - 1))][j - 1];
     50     }
     51     inline int query(int a, int b)
     52     {
     53         if (a > b) swap(a, b); 
     54         int k = mm[b - a + 1]; 
     55         return rmq[dp[a][k]] <= rmq[dp[b - (1 << k) + 1][k]] ? dp[a][k] : dp[b - (1 << k) + 1][k];
     56     }
     57 }st;
     58 
     59 inline void DFS(int u, int pre)
     60 {
     61     F[++cnt] = u;
     62     rmq[cnt] = deep[u]; 
     63     P[u] = cnt;
     64     for (int it = head[u]; ~it; it = edge[it].nx)
     65     {
     66         int v = edge[it].to;
     67         if (v == pre) continue;
     68         deep[v] = deep[u] + 1;
     69         DFS(v, u);
     70         F[++cnt] = u;
     71         rmq[cnt] = deep[u];
     72     }
     73 }
     74 
     75 inline void LCA_Init(int root, int node_num)
     76 {
     77     cnt = 0; deep[1] = 0;
     78     DFS(root, root);
     79     st.init(2 * node_num - 1);
     80 
     81 }
     82 
     83 inline int query_lca(int u, int v)
     84 {
     85     return F[st.query(P[u], P[v])];
     86 }
     87 
     88 inline void Run()
     89 {
     90     scanf("%d", &t);
     91     while (t--)
     92     {
     93         scanf("%d%d", &n, &m); Init();
     94         for (int i = 1, x; i <= m; ++i)
     95         {
     96             scanf("%d", &x);
     97             vis[x] = true;
     98         }
     99         for (int i = 1, u, v; i < n; ++i)
    100         {
    101             scanf("%d%d", &u, &v);
    102             addedge(u, v);
    103         }
    104         LCA_Init(1, n);
    105         int ans = 0;
    106         for (int i = 1; i <= n; ++i)
    107         {
    108             if (!vis[i]) continue;
    109             for (int j = 1; j <= n; ++j)
    110             {
    111                 if (!vis[j] || j == i) continue;
    112                 int lca = query_lca(i, j);
    113                 //printf("%d %d %d
    ", i, j, lca);
    114                 ans = max(ans, deep[i] + deep[j] - 2 * deep[lca]);
    115             }
    116         }
    117         printf("%d.00
    ", ans / 2);
    118     }
    119 }
    120 
    121 int main()
    122 {
    123     #ifdef LOCAL
    124         freopen("Test.in", "r", stdin);
    125     #endif
    126 
    127     Run();
    128     
    129     return 0;
    130 }
    View Code

    E - Square Network

    留坑。

    F - Permutation

    题意:给出一个n,里面有1-n,构造一个数列使得满足题目要求

    思路:142536  类似这样构造

     1 #include <bits/stdc++.h>
     2 
     3 using namespace std;
     4 
     5 #define N 100010
     6 
     7 int t, n;
     8 int arr[N];
     9 
    10 int main()
    11 {
    12     scanf("%d", &t);
    13     while (t--)
    14     {
    15         scanf("%d", &n);
    16         int cnt = 1;
    17         for (int i = 1; i <= n; i += 2)
    18             arr[i] = cnt++;
    19         for (int i = 2; i <= n; i += 2)
    20             arr[i] = cnt++;
    21         for (int i = 1; i <= n; ++i) printf("%d%c", arr[i], " 
    "[i == n]);
    22     }
    23     return 0;
    24 }
    View Code

    G - Debug

    留坑。

    H - A Simple Stone Game

    题意:有n堆石子,每次可以移动一个石子要另一堆,如果某一次移动之后,每一堆的石子个数都是x(x > 1) 的倍数,那么游戏结束,问最少需要移动多少个石子使得游戏结束

    思路:x一定是石子和的因数,我们可以枚举石子和的每个因数,求出每个因数下的移动次数,取min。至于如何求移动次数,我们可以将每个石子的余数记录下来,并将余数相加再除以因数,可以的到有多少堆石子得到石子,然后再将需要减少的石子数相加就可以得到。注意当只有一个石子的时候为0;

     1 #include<bits/stdc++.h>
     2 
     3 using namespace std;
     4 
     5 typedef long long ll;
     6 const ll INFLL = 0x3f3f3f3f3f3f3f3f;
     7 const int maxn = 1e5 + 10;
     8 
     9 int n;
    10 ll arr[maxn];
    11 ll sum;
    12 ll ans;
    13 int cnt;
    14 ll brr[maxn];
    15 ll crr[maxn];
    16 
    17 int tot;
    18 ll prime[maxn];
    19 bool isprime[maxn];
    20 
    21 inline void Init_prime()
    22 {
    23     memset(isprime, true, sizeof isprime);
    24     isprime[0] = isprime[1] = false;
    25     for(int i = 2; i < maxn; ++i)
    26     {
    27         if(isprime[i] == true)
    28         {
    29             prime[tot++] = i;
    30             for(int j = i << 1; j < maxn; j += i)
    31             {
    32                 isprime[j] = false;
    33             }
    34         }
    35     }
    36 }
    37 
    38 inline void cal(ll x)
    39 {
    40     ll sum_tmp = 0;
    41     int pos = 0;
    42     for(int i = 1; i <= n; ++i)
    43     {
    44         if(arr[i] % x)
    45         {
    46             crr[pos++] = arr[i] % x;
    47             sum_tmp += arr[i] % x;
    48         }
    49     }
    50     ll p = sum_tmp / x;
    51     sort(crr, crr + pos);
    52     ll res = 0;
    53     for(int i = 0; i < pos - p; ++i)
    54     {
    55         res += crr[i];
    56     }
    57     ans = min(ans, res);
    58 }
    59 
    60 inline void get_x(ll tmp)
    61 {
    62     ll tmp_ = sqrt(tmp) + 1;
    63     for(int i = 0; i < tot && prime[i] <= tmp_; ++i)
    64     {
    65         if(tmp % prime[i] == 0)
    66         {
    67             cal(prime[i]);
    68         }
    69     }
    70 }
    71 
    72 int main()
    73 {
    74     Init_prime();
    75     int t;
    76     scanf("%d",&t);
    77     while(t--)
    78     {
    79         scanf("%d", &n);
    80         sum = 0;
    81         for(int i = 1; i <= n; ++i)
    82         {
    83             scanf("%lld", arr + i);
    84             sum += arr[i];
    85         }
    86         ans = INFLL;
    87         get_x(sum);
    88         cal(sum);
    89         printf("%lld
    ", ans);
    90         
    91     }
    92     return 0;
    93 }
    View Code
    I - Cow`s Segment
    留坑。
     
    J - Interview
    留坑。
     
    K - Server
    题意:给出一些区间,每个区间附加两个值ai 和 bi  选出一些区间覆盖1 - t  并且 sgm(ai) / sgm(bi) 最小
    思路:二分答案 那么 就是使得 sgm(ai) - sgm(bi) * x >0
    然后 ai - bi * x > 0 的都选,,剩下的就是用最小代价覆盖所有区间 dp + 数据结构
    我是用线段树和树状数组,本来以为动态开点线段树会比普通线段树要快一点,实际上没有
    线段树
      1 #include <cstdio>
      2 #include <algorithm>
      3 #include <iostream>
      4 using namespace std;  
      5 
      6 #define N 100010
      7 #define ll long long
      8 #define INF 0x3f3f3f3f
      9 
     10 const double eps = 1e-4;
     11 
     12 struct node
     13 {
     14     int l, r;
     15     double Min;
     16     inline node() {}
     17     inline node(int l, int r, double Min) : l(l), r(r), Min(Min) {}
     18 }tree[N << 2];
     19 
     20 int cnt, root;
     21 
     22 inline void Init()
     23 {
     24     cnt = 1; root = 1;
     25     tree[1] = node(0, 0, INF * 1.0); 
     26 }
     27 
     28 inline void update(int &id, int l, int r, int ql, int qr, double val) 
     29 {
     30     if (id == 0)
     31     {
     32         id = ++cnt;  
     33         tree[id] = node(0, 0, val);
     34     }
     35     if (l >= ql && r <= qr)
     36     {
     37         tree[id].Min = min(tree[id].Min, val);  
     38         return;
     39     }
     40     int mid = (l + r) >> 1;
     41     if (ql <= mid) update(tree[id].l, l, mid, ql, qr, val);
     42     if (qr > mid) update(tree[id].r, mid + 1, r, ql, qr, val);
     43 }
     44 
     45 double ansMin; 
     46 
     47 inline void query(int id, int l, int r, int pos)
     48 {
     49     if (id == 0) return;
     50     ansMin = min(ansMin, tree[id].Min); 
     51     if (l == r)
     52         return;
     53     int mid = (l + r) >> 1;
     54     if (pos <= mid) query(tree[id].l, l, mid, pos); 
     55     else query(tree[id].r, mid + 1, r, pos);
     56 }
     57 
     58 struct Interval
     59 {
     60     int l, r; double a, b;
     61     inline void scan()
     62     {
     63         scanf("%d%d%lf%lf", &l, &r, &a, &b);
     64     }
     65     inline bool operator < (const Interval &r) const 
     66     {
     67         return l < r.l;
     68     }
     69 }interval[N];
     70 
     71 int T;
     72 int n, t;
     73 
     74 inline bool check(double x)
     75 {
     76     double sum = 0.0;
     77     for (int i = 1; i <= n; ++i)
     78         if (interval[i].a - interval[i].b * x < 0)
     79             sum += interval[i].a - interval[i].b * x;
     80     Init();
     81     update(root, 0, t, 0, 0, 0.0);
     82     for (int i = 1; i <= n; ++i)
     83     {
     84         ansMin = INF * 1.0; query(root, 0, t, interval[i].l - 1);
     85         ansMin = max(ansMin, ansMin + interval[i].a - interval[i].b * x);
     86         update(root, 0, t, interval[i].l, interval[i].r, ansMin);
     87     }
     88     ansMin = INF * 1.0; query(root, 0, t, t); 
     89     return sum + ansMin > 0;  
     90 }
     91 
     92 inline void Run()
     93 {
     94     scanf("%d", &T);
     95     while (T--)
     96     {
     97         scanf("%d%d", &n, &t); 
     98         for (int i = 1; i <= n; ++i)
     99             interval[i].scan();
    100         sort(interval + 1, interval + 1 + n);
    101         double l = 0, r = 1000 * 1.0;
    102         while (r - l > eps)
    103         {
    104             double mid = (l + r) / 2;
    105             if (check(mid))
    106                 l = mid;
    107             else
    108                 r = mid;
    109         }
    110         printf("%.3f
    ", l);
    111     }
    112 }
    113 
    114 int main()
    115 {
    116     #ifdef LOCAL
    117         freopen("Test.in", "r", stdin);
    118     #endif
    119 
    120     Run();
    121     
    122     return 0;
    123 }
    View Code

    树状数组

     1 #include <cstdio>
     2 #include <algorithm>
     3 #include <iostream>
     4 using namespace std;  
     5 
     6 #define N 100010
     7 #define ll long long
     8 #define INF 0x3f3f3f3f
     9 
    10 const double eps = 1e-4;
    11 
    12 double a[N];
    13 int T, n, t;
    14 
    15 inline int lowbit(int x)
    16 {
    17     return x & (-x);
    18 }
    19 
    20 inline void update(int x, double val)
    21 {
    22     for (int i = x; i > 0; i -= lowbit(i))
    23         a[i] = min(a[i], val);
    24 }
    25 
    26 inline double query(int x)
    27 {
    28     if (x == 0) return 0;
    29     double res = INF;
    30     for (int i = x; i <= t; i += lowbit(i))
    31         res = min(a[i], res);
    32     return res;
    33 }
    34 
    35 struct Interval
    36 {
    37     int l, r; double a, b;
    38     inline void scan()
    39     {
    40         scanf("%d%d%lf%lf", &l, &r, &a, &b);
    41     }
    42     inline bool operator < (const Interval &r) const 
    43     {
    44         return l < r.l;
    45     }
    46 }interval[N];
    47 
    48 inline bool check(double mid)
    49 {
    50     double sum = 0.0;
    51     for (int i = 1; i <= n; ++i)
    52         if (interval[i].a - interval[i].b * mid < 0)
    53             sum += interval[i].a - interval[i].b * mid;
    54     for (int i = 0; i <= t; ++i) a[i] = INF;
    55     for (int i = 1; i <= n; ++i)
    56     {
    57         double x = query(interval[i].l - 1);
    58         x = max(x, interval[i].a - interval[i].b * mid);
    59         update(interval[i].r, x); 
    60     }
    61     return sum + query(t) > 0;
    62 }
    63 
    64 inline void Run()
    65 {
    66     scanf("%d", &T);
    67     while (T--)
    68     {
    69         scanf("%d%d", &n, &t); 
    70         for (int i = 1; i <= n; ++i)
    71             interval[i].scan();
    72         sort(interval + 1, interval + 1 + n);
    73         double l = 0, r = 1000 * 1.0;
    74         while (r - l > eps)
    75         {
    76             double mid = (l + r) / 2;
    77             if (check(mid))
    78                 l = mid;
    79             else
    80                 r = mid;
    81         }
    82         printf("%.3f
    ", l);
    83     }
    84 }
    85 
    86 int main()
    87 {
    88     #ifdef LOCAL
    89         freopen("Test.in", "r", stdin);
    90     #endif
    91 
    92     Run();
    93     
    94     return 0;
    95 }
    View Code
     
     
    L - Color a Tree
    题意:给出两条规则: A , 以x为根的子树下的黑点数量不小于y  B : 除了以x为根的子树下的黑点数量不小于y ,求满足给出的所有规则,需要染色的最小数量
    思路:假如我们知道答案,那么B规则就可以转变为以x为根的子树下的黑点数量不大于(ans - y)
    然后二分,DFScheck
      1 #include <bits/stdc++.h>
      2 using namespace std; 
      3 
      4 #define N 100010
      5 
      6 struct Edge
      7 {
      8     int to, nx;
      9     inline Edge() {}
     10     inline Edge(int to, int nx) : to(to), nx(nx) {}
     11 }edge[N << 1];
     12 
     13 int n;
     14 int head[N], pos;
     15 int son[N];
     16 int A[N], B[N], C[N];
     17 
     18 inline void Init()
     19 {
     20     memset(head, -1, sizeof head);
     21     memset(son, 0, sizeof son);
     22     memset(A, 0, sizeof A);
     23     memset(B, 0, sizeof B);
     24     pos = 0; 
     25 }
     26 
     27 inline void addedge(int u, int v) 
     28 {
     29     edge[++pos] = Edge(v, head[u]); head[u] = pos;
     30     edge[++pos] = Edge(u, head[v]); head[v] = pos;
     31 }
     32 
     33 inline void DFS_PRE(int u, int pre)
     34 {
     35     son[u] = 1; int cnt = 0;
     36     for (int it = head[u]; ~it; it = edge[it].nx)
     37     {
     38         int v = edge[it].to; 
     39         if (v == pre) continue;
     40         DFS_PRE(v, u);
     41         cnt += A[v];
     42         son[u] += son[v];    
     43     }
     44     A[u] = max(A[u], cnt);
     45 }
     46 
     47 inline void DFS_CHECK(int u, int pre)
     48 {
     49     int cnt = 1;
     50     for (int it = head[u]; ~it; it = edge[it].nx)
     51     {
     52         int v = edge[it].to;
     53         if (v == pre) continue;
     54         DFS_CHECK(v, u);  
     55         cnt += C[v];
     56     }
     57     C[u] = min(C[u], cnt);
     58 }
     59 
     60 inline bool check(int mid) 
     61 {
     62     for (int i = 1; i <= n; ++i)
     63     {
     64         C[i] = mid - B[i];
     65         if (A[i] > son[i] || B[i] > (n - son[i]) || A[i] > C[i]) return false;
     66     }
     67     //for (int i = 1; i <= n; ++i) printf("%d %d
    ", i, C[i]);
     68     DFS_CHECK(1, 1); 
     69     //printf("bug -> %d
    ", mid);
     70     //for (int i = 1; i <= n; ++i) printf("%d %d
    ", i, C[i]);
     71     for (int i = 1; i <= n; ++i)
     72     {
     73         if (A[i] > C[i]) return false; 
     74     }
     75     return C[1] >= mid;
     76 }
     77 
     78 inline void Run()
     79 {
     80     int t; scanf("%d", &t);
     81     while (t--)
     82     {
     83         scanf("%d", &n); Init();
     84         for (int i = 1, u, v; i < n; ++i)
     85         {
     86             scanf("%d%d", &u, &v);
     87             addedge(u, v);
     88         }
     89         int tot, u, v;
     90         scanf("%d", &tot); 
     91         while (tot--)
     92         {
     93             scanf("%d%d", &u, &v);
     94             A[u] = max(A[u], v);
     95         }
     96         scanf("%d", &tot);
     97         while (tot--) 
     98         {
     99             scanf("%d%d", &u, &v);
    100             B[u] = max(B[u], v); 
    101         }
    102         DFS_PRE(1, 1);
    103         int l = 0, r = n, ans = -1;
    104         while (r - l >= 0)
    105         {
    106             int mid = (l + r) >> 1; 
    107             if (check(mid))
    108             {
    109                 ans = mid;
    110                 r = mid - 1;
    111             }
    112             else
    113                 l = mid + 1;
    114         }
    115         printf("%d
    ", ans);
    116     }
    117 }
    118 
    119 int main()
    120 {
    121     #ifdef LOCAL
    122         freopen("Test.in", "r", stdin);
    123     #endif
    124 
    125     Run();
    126     
    127     return 0;
    128 }
    View Code
     
    M - Geometry Problem
    题意:给出n个点,求一个圆心以及半径,使得有一半以上的点在这个圆上
    思路:随机选三个点,构成外接圆 判断一下 是不是 n <= 4 的时候 特判
     
     
      1 #include <bits/stdc++.h>
      2 using namespace std; 
      3 
      4 const double eps = 1e-3;
      5 
      6 inline int sgn(double x)
      7 {
      8     if (fabs(x) < eps) return 0;
      9     if (x < 0) return -1;
     10     return 1;
     11 }
     12 
     13 struct Point
     14 {
     15     double x, y;
     16     inline Point() {}
     17     inline Point(double x, double y) : x(x), y(y) {}
     18     inline void scan() { scanf("%lf%lf", &x, &y); }
     19     inline Point operator + (const Point &b) const { return Point(x + b.x, y + b.y); }
     20     inline Point operator - (const Point &b) const { return Point(x - b.x, y - b.y); }
     21     inline Point operator / (const double &k) const { return Point(x / k, y / k); }
     22     inline Point operator * (const double &k) const { return Point(x * k, y * k); }
     23     inline double operator ^ (const Point &b) const { return x * b.y - y * b.x; }
     24     inline double operator * (const Point &b) const { return x * b.x + y * b.y; }
     25     inline double distance(Point b) { return hypot(x - b.x, y - b.y); }
     26     inline Point rotleft() { return Point(-y, x); }
     27 };
     28 
     29 struct Line
     30 {
     31     Point s, e;
     32     inline Line() {}
     33     inline Line(Point s, Point e) : s(s), e(e) {}
     34     inline Point crosspoint(Line v)
     35     {
     36         double a1 = (v.e - v.s) ^ (s - v.s);
     37         double a2 = (v.e - v.s) ^ (e - v.s);
     38         return Point((s.x * a2 - e.x * a1) / (a2 - a1), (s.y * a2 - e.y * a1) / (a2 - a1));
     39     }
     40     inline int relation(Point p)
     41     {
     42         int c = sgn((p - s) ^ (e - s));
     43         if (c < 0) return 1;
     44         if (c > 0) return 2;
     45         return 3;
     46     }
     47 };
     48 
     49 struct Circle
     50 {
     51     Point p;
     52     double r;
     53     inline Circle() {}
     54     inline Circle(Point p, double r) : p(p), r(r) {}
     55     inline Circle(Point a, Point b, Point c)
     56     {
     57         Line u = Line((a + b) / 2, ((a + b) / 2) + ((b - a).rotleft()));
     58         Line v = Line((b + c) / 2, ((b + c) / 2) + ((c - b).rotleft()));
     59         p = u.crosspoint(v);
     60         r = p.distance(a);
     61     }
     62 };
     63 
     64 int t, n;
     65 vector <Point> v;
     66 
     67 inline void Run()
     68 {
     69     scanf("%d", &t);
     70     while (t--)
     71     {
     72         scanf("%d", &n);
     73         double x, y; v.clear();
     74         for (int i = 1; i <= n; ++i)
     75         {
     76             scanf("%lf%lf", &x, &y);
     77             v.emplace_back(x, y);
     78         }
     79         if (n == 1)
     80         {
     81             printf("%.6f %.6f 0
    ", v[0].x, v[0].y); 
     82             continue;
     83         }
     84         else if (n <= 4)
     85         {
     86             Point ans = Point((v[0].x + v[1].x) / 2, (v[0].y + v[1].y) / 2);
     87             double dis = ans.distance(v[0]);
     88             printf("%.6f %.6f %.6f
    ", ans.x, ans.y, dis); 
     89             continue;
     90         }
     91         else
     92         {
     93             Circle cir;
     94             while (true)
     95             {
     96                 random_shuffle(v.begin(), v.end());  
     97                 //if (Line(v[0], v[1]).relation(v[2]) == 3) continue; 
     98                 cir = Circle(v[0], v[1], v[2]); 
     99                 int cnt = 3;
    100                 for (int i = 3, len = v.size(); i < len; ++i)
    101                     if (fabs(cir.p.distance(v[i]) - cir.r) < eps) ++cnt; 
    102                 if (cnt >= ((n + 1) >> 1))
    103                     break;
    104             }
    105             printf("%.6f %.6f %.6f
    ", cir.p.x, cir.p.y, cir.r);
    106         }
    107     }
    108 }
    109 
    110 int main()
    111 {
    112     #ifdef LOCAL
    113         freopen("Test.in", "r", stdin);
    114     #endif
    115 
    116     Run();
    117     
    118     return 0;
    119 }
    View Code
  • 相关阅读:
    Linux Shell中管道的原理及C实现框架
    标准文件描述符与标准文件句柄
    Makefile:如何写目标依赖
    CODING 携手优普丰,道器合璧打造敏捷最佳实践
    CODING 邀您参与品牌认知度调查 赢得机会领取猴子抱枕好礼
    敏捷,持续集成/持续交付, DevOps 三者的区别
    从 IT 到 DevOps 实践
    腾讯云大学 x CODING | 远程协作办公新模式
    共同战“疫”,CODING 帮助研发团队高效协同
    研发团队远程办公——如何应用硬核工具无间协作?
  • 原文地址:https://www.cnblogs.com/Dup4/p/9524963.html
Copyright © 2020-2023  润新知