Codeforces Round #737 (Div. 2)

Codeforces Round #737 (Div. 2)

A. Ezzat and Two Subsequences

  • 题意

你可以将一个序列分成两边,\(f(a)\)表示序列集合为\(a\)内所有数的平均值是多少?
然后求最大的\(f(a) + f(b)\)

  • 思路

记录最大值和总和即可算最大的。

code :

int a[N];
void solve(){
    int n;
    cin >> n;
    int maxn = -INF, sum = 0;
    fep(i,1,n) {
        cin >> a[i];
        maxn = max(maxn, a[i]);
        sum += a[i];
    }
    db ans = maxn + 1.0 * (sum - maxn) / (n - 1); 
    pr("%.7f\n",ans);
} 

B. Moamen and k-subarrays

  • 题意

给一个长度为\(n\)序列\(a\), 可以将他的子序列分成\(k\)个,你可以重新排列这k个序列后,然后满足整个序列有序即可。

  • 思路

将整个序列离散化,然后判断前一个和后一个的大小即可

code :

vector<int> v;
int a[N];
void solve(){
    int n,m;
    cin >> n >> m;
    v.clear();
    for(int i = 1;i <= n;i ++) {
        cin >> a[i];
        v.pb(a[i]);
    }
    sort(v.begin(), v.end());
    v.erase(unique(v.begin(), v.end()),  v.end());
    fep(i,1,n) a[i] = lower_bound(v.begin(), v.end(), a[i]) - v.begin() + 1;
    int ans = n;
    fep(i,2,n) if(a[i] == a[i - 1] + 1) ans --;
    if(ans <= m) cout << "YES" << endl;
    else cout << "NO" << endl;
}

C. Moamen and XOR

  • 题意

给出\(n,k\),表示序列\(a\)长度为\(n\), 且每个\(a_i <2 ^k\)
问存在多少序列\(a\),满足:
\(a_1 \,\&\, a_2 \,\&\, a_3 \,\&\, \ldots \,\&\, a_n \ge a_1 \oplus a_2 \oplus a_3 \oplus \ldots \oplus a_n\)

  • 思路

首先对每个二进制来说,如果且操作为1,那么所有这一位都是1,而亦或操作只要出现奇数个1即可,那么就要分奇偶来判断了。

  1. 奇数不存在\(a > b\)的存在,只有\(a <= b的情况\),那么我们就只要算出相等的情况即可。
    对于每个二进制要么都是0,要么都是1,那么1很简单,都是1,就一种情况。而0,就可以是各种情况了\(C_n^0 + C_n^2 + C_n^4 \cdots = 2^{n - 1}\)
    那么奇数就是\((2^{n-1} + 1)^k\)
  2. 然后就要判偶数了的存在了。
    那么偶数可以出现\(a > b\)的情况,那么我们就要枚举最高位的大小了,二进制中从最高位到最低位,第一个出现\(a_i != b_i\)的情况,然后后面的随意排都行,必须是\(a_i > b_i\),那么就\(k\)次枚举即可
    然后相等的情况和上面的类似不过要减去一个\(C_n^n\), 因为全1的情况不同, 及\((2^{n-1} - 1)^k\)
    即为ans = \((2^{n-1} - 1)^k + \sum_{i=1}^k(2^{n-1} - 1)^{i-1} * (2^n)^{k-i}\)

code :

void solve(){
    int n, k;
    cin >> n >> k;
    if(n & 1) {
        ll ans = pow_mod(2,n - 1) + 1;
        ans = pow_mod(ans, k);
        cout << ans << endl;
    }else {
        ll d = pow_mod(2,n - 1) - 1;
        ll c = pow_mod(2,n);
        ll ans = pow_mod(d, k);
        for(int i = 1;i <= k;i ++) {
            ans = (ans + pow_mod(d, i - 1) * pow_mod(c, k - i) % mod + mod) % mod;
        }
        cout << ans << endl;
    }
}

D. Ezzat and Grid

  • 题意

给出一张01序列图,\(n\)\(10^9\)列,让你取删最少的行,令任意一行,都存在某一列和其他行的某一列相同且都为1。求出需要删除的最少行。

  • 思路

开线段树存储最大值即可,并多存一个行数,并开个\(pre_i\)记录前一个,找到相应最大的方案,那么其他就都删了满足最少。

code :

const int N = 600100;
#define mid (l + r >> 1)
#define lsn (u << 1)
#define rsn (u << 1 | 1)
vector<int> v;
int n,m;
struct node {
    int id,l,r;
}q[N];

pii sum[N << 2], laz[N << 2];

void pushup(int u) {
    sum[u] = max(sum[lsn], sum[rsn]);
}

void up(int u,pii k) {
    sum[u] = max(sum[u], k);
    laz[u] = max(laz[u], k);
}

void down(int u,int l,int r) {
    if(!laz[u].first) return;
    up(lsn,laz[u]);
    up(rsn,laz[u]);
    laz[u].first = laz[u].second = 0;
}

void update(int L,int R,pii v,int u,int l,int r) {
    if(L <= l && R >= r) {
        up(u,v);
        return;
    }
    down(u,l,r);
    if(L <= mid) update(L,R,v,lsn,l,mid);
    if(R > mid) update(L,R,v,rsn,mid + 1,r);
    pushup(u);
}

pii query(int L,int R,int u,int l,int r) {
    if(L <= l && R >= r) {
        return sum[u];
    }
    down(u,l,r);
    if(R <= mid) return query(L,R,lsn,l,mid);
    if(L > mid) return query(L,R,rsn,mid + 1,r);
    return max(query(L,R,lsn,l,mid), query(L,R,rsn,mid + 1,r));
}

vector<pii> g[N];
int pre[N];
bool st[N];
void solve(){
    cin >> n >> m;
    for(int i = 1;i <= m;i ++) {
        cin >> q[i].id >> q[i].l >> q[i].r;
        v.push_back(q[i].l);
        v.push_back(q[i].r);
    }
    sort(v.begin(), v.end());
    v.erase(unique(v.begin(), v.end()), v.end());
    int sz = v.size();
    fep(i,1,m){
        q[i].l = lower_bound(v.begin(), v.end(), q[i].l) - v.begin() + 1;
        q[i].r = lower_bound(v.begin(), v.end(), q[i].r) - v.begin() + 1;
        g[q[i].id].pb({q[i].l,q[i].r});
    }
    int flag = 0;
    pii ans = pii{0,0};
    for(int i = 1;i <= n;i ++) {
        pii now = pii{0,0};
        for(auto it : g[i]) {
            now = max(now, query(it.first, it.second,1,1,sz));
        }
        pre[i] = now.second;
        now = pii{now.first + 1, i};
        for(auto it : g[i]) {
            update(it.first,it.second,now,1,1,sz);
        }
        ans = max(ans, now);
    }
    cout << n - ans.first << endl;
    int k = ans.second;
    while(k) {
        st[k] = 1;
        k = pre[k];
    }

    for(int i = 1;i <= n;i ++) {
        if(!st[i]) {
            cout << i << ' ';
        }
    }
}
posted @ 2021-08-11 19:16  darker_wxl  阅读(69)  评论(0编辑  收藏  举报
window.onload = function(){ $("#live2dcanvas").attr("style","position: fixed; opacity: 0.7; left: 70px; bottom: 0px; z-index: 1; pointer-events: none;") }