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 << '\n'; }
  template<typename T, typename...Args>
  void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
#else
  #define dbg(...)
#endif
void pt() {std::cout << '\n'; }
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 << '\n';   
                return;
            }
        }
        cout << ans + 2 << '\n';
    } else cout << ans << '\n';
}
 
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 << '\n'; }
  template<typename T, typename...Args>
  void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
#else
  #define dbg(...)
#endif
void pt() {std::cout << '\n'; }
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] << '\n';
}
 
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 << '\n'; }
  template<typename T, typename...Args>
  void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
#else
  #define dbg(...)
#endif
void pt() {std::cout << '\n'; }
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 << '\n'; }
  template<typename T, typename...Args>
  void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
#else
  #define dbg(...)
#endif
void pt() {std::cout << '\n'; }
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" << '\n';
        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" << '\n'; 
            return;
        }   
    }
    cout << "YES" << '\n';
}
 
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\not ={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 << '\n'; }
  template<typename T, typename...Args>
  void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
#else
  #define dbg(...)
#endif
void pt() {std::cout << '\n'; }
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] << '\n';
}
 
int main() {
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    cout << fixed << setprecision(20);
    while(cin >> n) run();
    return 0;
}
posted @ 2020-02-10 10:41  heyuhhh  阅读(230)  评论(0编辑  收藏  举报