Codeforces Round #569 (Div. 1)

Codeforces Round #569 (Div. 1)
A:
首先模拟一段,等最大值到第一个的时候会开始循环。

#include <bits/stdc++.h>
using namespace std;
const int N = 3e5+7;
int a[N];
int ansx[N], ansy[N];
using ll = long long;
int main() {
    int n, q;
    scanf("%d%d", &n, &q);
    for(int i=0; i<n; ++i) scanf("%d", &a[i]);
    int mx = 0;
    for(int i=0; i<n; ++i) mx=max(mx, a[i]);
    int p =0;
    for(; p<n; ++p) if(a[p]==mx) break;
    for(int i=0; i<p; ++i) {
        ansx[i+1] = a[i];
        ansy[i+1] = a[i+1];
        if(a[i]>a[i+1]) {
            a[i+n]=a[i+1];
            a[i+1]=a[i];
        } else {
            a[i+n]=a[i];
        }
    }
    while(q--) {
        ll m;
        scanf("%I64d", &m);
        if(m<=p) printf("%d %d\n", ansx[m], ansy[m]);
        else {
            int id=(m-p-1)%(n-1);
            printf("%d %d\n", a[p], a[p+id+1]);
        }
    }
    return 0;
}

B:
考虑一维坐标轴完成相同任务,假设坐标轴长度为10,那么0,10,1,9,2,8,…这种方案显然满足条件。那么对于二维坐标轴其实每个点可以唯一地映射到一个一维坐标轴,那么映射过去就行了。

#include <bits/stdc++.h>
using namespace std;
int main() {
    int n, m;
    scanf("%d%d", &n, &m);
    int cur=0, diff=n*m-1;
    for(int i=0; i<n*m; ++i) {
        int x = cur/m+1;
        int y = cur%m+1;
        cur+=diff;
        if(diff>0) {
            diff=-diff+1;
        } else {
            diff=-diff-1;
        }
        printf("%d %d\n", x, y);
    }
}

C:
对于所有pupil :在 [ 1 , b [ i ] ] [1, b[i]] [1,b[i]] 区间+1。
对于所有dished:在 [ 1 , a [ i ] ] [1,a[i]] [1,a[i]] 区间-1 。
可以看出,右边第一个小于0的点就是每次询问的答案。
对于每次修改,更新一下线段树就行。

#include <bits/stdc++.h>
#define lson (rt<<1)
#define rson (rt<<1|1)
using namespace std;
const int V = 1e6+7;
const int N = 3e6+7;
int lz[V<<2], mn[V<<2];
void push_down(int rt) {
    if(lz[rt]) {
        lz[lson] += lz[rt];
        lz[rson] += lz[rt];
        mn[lson] += lz[rt];
        mn[rson] += lz[rt];
        lz[rt]=0;
    }
}
void push_up(int rt) {
    mn[rt] = min(mn[lson], mn[rson]);
}
void update(int rt, int l, int r, int ql, int qr, int val) {
    if(ql<=l&&qr>=r) {
        lz[rt] += val;
        mn[rt] += val;
        return;
    }
    push_down(rt);
    int m = (l+r)/2;
    if(ql<=m) update(lson, l, m, ql, qr, val);
    if(qr>m) update(rson, m+1, r, ql, qr, val);
    push_up(rt);
}
int query(int rt, int l, int r) {
    if(l==r) return l;
    push_down(rt);
    int m = (l+r)/2;
    int res;
    if(mn[rson]<0) res = query(rson, m+1, r);
    else res = query(lson, l, m);
    push_up(rt);
    return res;
}
int a[N], b[N];
int main() {
    int n, m, q;
    scanf("%d%d", &n, &m);
    int vn = 1000000;
    for(int i=1; i<=n; ++i) {
        scanf("%d", &a[i]);
        update(1, 1, vn, 1, a[i], -1);
    }
    for(int i=1; i<=m; ++i) {
        scanf("%d", &b[i]);
        update(1, 1, vn, 1, b[i], 1);
    }
    scanf("%d", &q);
    while(q--) {
        int op, i, x;
        scanf("%d%d%d", &op, &i, &x);
        if(op==1) {
            update(1, 1, vn, 1, a[i], 1);
            a[i] = x;
            update(1, 1, vn, 1, a[i], -1);
        } else {
            update(1, 1, vn, 1, b[i], -1);
            b[i] = x;
            update(1, 1, vn, 1, b[i], 1);
        }
        int ans;
        if(mn[1]>=0) ans = -1;
        else ans = query(1, 1, vn);
        printf("%d\n", ans);
    }
    return 0;
}

D:
好像是斜率优化DP,待补。。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值