Codeforces Round #618 (Div. 2)

传送门

A. Non-zero

签到。

Code
/*
 * Author:  heyuhhh
 * Created Time:  2020/2/9 22:07:26
 */
#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
#include <cmath>
#include <set>
#include <map>
#include <queue>
#include <iomanip>
#define MP make_pair
#define fi first
#define se second
#define sz(x) (int)(x).size()
#define all(x) (x).begin(), (x).end()
#define INF 0x3f3f3f3f
#define Local
#ifdef Local
  #define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
  void err() { std::cout << '
'; }
  template<typename T, typename...Args>
  void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
#else
  #define dbg(...)
#endif
void pt() {std::cout << '
'; }
template<typename T, typename...Args>
void pt(T a, Args...args) {std::cout << a << ' '; pt(args...); }
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
//head
const int N = 100 + 5;
 
int n;
int a[N];
 
void run(){
    cin >> n;
    for(int i = 1; i <= n; i++) cin >> a[i];
    int sum = 0, ans = 0;
    for(int i = 1; i <= n; i++) {
        if(a[i] == 0) ++ans, ++a[i];
        sum += a[i];
    }
    if(sum == 0) {
        for(int i = 1; i <= n; i++) {
            if(a[i] != -1) {
                cout << ans + 1 << '
';   
                return;
            }
        }
        cout << ans + 2 << '
';
    } else cout << ans << '
';
}
 
int main() {
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    cout << fixed << setprecision(20);
    int T; cin >> T;
    while(T--) run();
    return 0;
}

B. Assigning to Classes

贪心即可。
我们选出的两个数中,假设在左边的为(a),右边的为(b),那么小于(a)的有(x)个,大于(a)的有(x)个;同理小于(b)和大于(b)的都有(y)个。那么左侧为(x+y)个,右侧为(x+y)个。
所以推出最后选出的(a,b)位置是对称的,因为选最中间的两个即可。

Code
/*
 * Author:  heyuhhh
 * Created Time:  2020/2/9 22:17:29
 */
#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
#include <cmath>
#include <set>
#include <map>
#include <queue>
#include <iomanip>
#define MP make_pair
#define fi first
#define se second
#define sz(x) (int)(x).size()
#define all(x) (x).begin(), (x).end()
#define INF 0x3f3f3f3f
#define Local
#ifdef Local
  #define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
  void err() { std::cout << '
'; }
  template<typename T, typename...Args>
  void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
#else
  #define dbg(...)
#endif
void pt() {std::cout << '
'; }
template<typename T, typename...Args>
void pt(T a, Args...args) {std::cout << a << ' '; pt(args...); }
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
//head
const int N = 2e5 + 5;
 
int n;
int a[N];
 
void run(){
    cin >> n;
    n *= 2;
    for(int i = 1; i <= n; i++) cin >> a[i];
    sort(a + 1, a + n + 1);
    cout << a[n / 2 + 1] - a[n / 2] << '
';
}
 
int main() {
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    cout << fixed << setprecision(20);
    int T; cin >> T;
    while(T--) run();
    return 0;
}

C. Anu Has a Function

题意:
定义(f(x,y)=(x|y)-y)
先给出序列(a),现在可以重新排列(a)的顺序,问最终(f(f(cdots f(f(a_1,a_2), a_3),cdots a_{n-1}),a_n))最大为多少。

思路:
(f)的表达式中可以知道,(f(x,y))的含义为:(x)的二进制位中,若某个二进制位为(1)(y)在这位也为(1),那么这位就变为(0)
然后我们按二进制位来分析,假设我们钦定了(a_1),若二进制第(k)位只有(a_1)才为(1),那么显然后面无论怎么安排,这位都将保留在答案中;否则,无论后面怎么安排,这位必然会被另一个(a_i)抵消。
因为要使得答案最大,我们贪心得选择(a_1)即可,选定之后,后面无论怎么安排,答案都唯一。

Code
/*
 * Author:  heyuhhh
 * Created Time:  2020/2/9 22:24:07
 */
#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
#include <cmath>
#include <set>
#include <map>
#include <queue>
#include <iomanip>
#define MP make_pair
#define fi first
#define se second
#define sz(x) (int)(x).size()
#define all(x) (x).begin(), (x).end()
#define INF 0x3f3f3f3f
#define Local
#ifdef Local
  #define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
  void err() { std::cout << '
'; }
  template<typename T, typename...Args>
  void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
#else
  #define dbg(...)
#endif
void pt() {std::cout << '
'; }
template<typename T, typename...Args>
void pt(T a, Args...args) {std::cout << a << ' '; pt(args...); }
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
//head
const int N = 1e5 + 5;
 
int n;
int a[N];
bool chk[N];
 
void run(){
    for(int i = 1; i <= n; i++) cin >> a[i];
    vector <int> v[31];
    for(int i = 30; i >= 0; i--) {
        for(int j = 1; j <= n; j++) {
            if(a[j] >> i & 1) {
                v[i].push_back(j);
            }  
        }
        if(sz(v[i]) == 1) {
            chk[v[i][0]] = true;
            break;   
        }
    }
    for(int i = 1; i <= n; i++) if(chk[i]) cout << a[i] << ' ';
    for(int i = 1; i <= n; i++) if(!chk[i]) cout << a[i] << ' ';
}
 
int main() {
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    cout << fixed << setprecision(20);
    while(cin >> n) run();
    return 0;
}

D. Aerodynamic

题意:
给出一个凸多边形,现在将其平移且保证原点被包含在凸多边形内部(包括边缘)。
最终画出的图形的并集也是一个凸多边形。
问这两个凸多边形是否相似。

思路:
观察样例得到一个结论:
若凸多边形关于重心对称,则最终是相似的。
至于证明并不会。

Code
/*
 * Author:  heyuhhh
 * Created Time:  2020/2/9 23:14:21
 */
#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
#include <cmath>
#include <set>
#include <map>
#include <queue>
#include <iomanip>
#define MP make_pair
#define fi first
#define se second
#define sz(x) (int)(x).size()
#define all(x) (x).begin(), (x).end()
#define INF 0x3f3f3f3f
#define Local
#ifdef Local
  #define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
  void err() { std::cout << '
'; }
  template<typename T, typename...Args>
  void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
#else
  #define dbg(...)
#endif
void pt() {std::cout << '
'; }
template<typename T, typename...Args>
void pt(T a, Args...args) {std::cout << a << ' '; pt(args...); }
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
//head
const int N = 1e5 + 5;
 
int n;
int x[N], y[N];
 
void run(){
    for(int i = 1; i <= n; i++) {
        cin >> x[i] >> y[i];   
    }
    x[n + 1] = x[1], y[n + 1] = y[1];
    if(n & 1) {
        cout << "NO" << '
';
        return;   
    }
    for(int i = 1; i <= n / 2; i++) {
        int j = i + n / 2;
        if(x[i + 1] - x[i] == x[j] - x[j + 1] && y[i + 1] - y[i] == y[j] - y[j + 1]) {}
        else {
            cout << "NO" << '
'; 
            return;
        }   
    }
    cout << "YES" << '
';
}
 
int main() {
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    cout << fixed << setprecision(20);
    while(cin >> n) run();
    return 0;
}

E. Water Balance

题意:
给出数组(a),现在可以执行任意次如下操作:

  • 选择一段区间(displaystyle [l,r]),将(displaystyle a_l,a_{l+1},cdots,a_r)变为(displaystyle frac{a_l+a_{l+1}+cdots+a_r}{r-l+1})

现在问最终字典序最小的(a)为多少。

思路:
首先容易得到一个结论,最终选择的区间一定是一段一段的,不会产生区间覆盖的情况,可以区间覆盖就可以将区间合并。
(pre_i)为数组(a)的前缀和,那么由(displaystyle frac{pre_r-pre_{l-1}}{r-(l-1)})这样的形式我们可以联想到斜率。
现在二维平面坐标系中有(n+1)个点,分别为((0,0),(1,pre_1),cdots,(n,pre_n)),那么现在我们的任务就是:从((0,0))出发,找到使得斜率最小的点((i,pre_i)),然后从((i,pre_i))出发...以此类推。
那么我们只需要用单调栈维护一个下凸壳就行,下凸壳有个很良好的性质,就是对于凸壳上的任意一条边((i,j)),不存在(t,t ot ={i,j}),使得(k_{ij}>k_{it})
代码如下:

Code
/*
 * Author:  heyuhhh
 * Created Time:  2020/2/9 22:49:45
 */
#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
#include <cmath>
#include <set>
#include <map>
#include <queue>
#include <iomanip>
#define MP make_pair
#define fi first
#define se second
#define sz(x) (int)(x).size()
#define all(x) (x).begin(), (x).end()
#define INF 0x3f3f3f3f
#define Local
#ifdef Local
  #define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
  void err() { std::cout << '
'; }
  template<typename T, typename...Args>
  void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
#else
  #define dbg(...)
#endif
void pt() {std::cout << '
'; }
template<typename T, typename...Args>
void pt(T a, Args...args) {std::cout << a << ' '; pt(args...); }
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
//head
const int N = 1e6 + 5;
 
int n;
int a[N];
double b[N];
ll pre[N];
int q[N];
 
void run(){
    for(int i = 1; i <= n; i++) cin >> a[i];
    for(int i = 1; i <= n; i++) {
        pre[i] = pre[i - 1] + a[i];
    }
    int top = 0;
    for(int i = 0; i <= n; i++) {
        if(top <= 1) {
            q[++top] = i;
            continue;
        }   
        while(top > 1 && 1ll * (pre[q[top]] - pre[q[top - 1]]) * (i - q[top]) >= 1ll * (pre[i] - pre[q[top]]) * (q[top] - q[top - 1])) {
            --top;
        }
        q[++top] = i;
    }
    for(int i = 1; i < top; i++) {
        double x = 1.0 * (pre[q[i + 1]] - pre[q[i]]) / (q[i + 1] - q[i]);
        for(int j = q[i] + 1; j <= q[i + 1]; j++) b[j] = x;
    }
    for(int i = 1; i <= n; i++) cout << b[i] << '
';
}
 
int main() {
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    cout << fixed << setprecision(20);
    while(cin >> n) run();
    return 0;
}
原文地址:https://www.cnblogs.com/heyuhhh/p/12290081.html