2021 CSP-J 题解

分糖果

其实题意就是要求x%n的最大值

我们可以吧min(kn-1,r)作为x来求x%n的最大值

k求法就是(l+1)/n向上取整   

 向上取整就直接分母+1就行 

int n, l, r;
cin >> n >> l >> r;
int t = min(r, (l + 1 + n - 1) / n * n - 1);
cout << t % n << endl;

插入排序

用分治来解决

第一维时间天然有序,第二维是元素大小pair<int,int>,分治的时候对其做归并,求出每个区间左半部分的修改操作对右半部分询问的贡献。

 

struct Node {
    int x, y, id;
    bool operator<(const Node &rhs) const {
        if (x == rhs.x) {
            if (y == rhs.y) return id < rhs.id;
            return y < rhs.y;
        }
        return x < rhs.x;
    }
} a[N];
int c[N];
int ans[N];

void solve(int l, int r) {
    if (l == r) return;
    int mid = (l + r) / 2;
    solve(l, mid);
    solve(mid + 1, r);
    int p1 = l, p2 = mid + 1, len = r - l + 1;
    int now = 0;
    for (int i = 0; i < len; i++) {
        if (p1 <= mid && (p2 > r || a[p1] < a[p2])) {
            if (a[p1].id == -1) now--;
            if (a[p1].id == 0) now++;
            p1++;
        } else {
            if (a[p2].id > 0) ans[a[p2].id] += now;
            p2++;
        }
    }
    inplace_merge(a + l, a + mid + 1, a + r + 1);
}
int main() {
    int n, m;
    scanf("%d%d", &n, &m);
    int tot = 0;
    for (int i = 1; i <= n; i++) {
        scanf("%d", &c[i]);
        a[++tot] = {c[i], i, 0};
    }
    int qid = 0;
    for (int i = 1; i <= m; i++) {
        int op, x, y;
        scanf("%d", &op);
        if (op == 1) {
            scanf("%d%d", &x, &y);
            a[++tot] = {c[x], x, -1};
            c[x] = y;
            a[++tot] = {c[x], x, 0};
        } else {
            scanf("%d", &x);
            a[++tot] = {c[x], x, ++qid};
        }
    }
    solve(1, tot);
    for (int i = 1; i <= qid; i++) {
        printf("%d\n", ans[i]);
    }
    return 0;
}

 网络连接

char s[N], ip[N];
map<LL, int> mp;

int main() {
    int n;
    scanf("%d", &n);
    for (int u = 1; u <= n; u++) {
        scanf("%s %s", s, ip);
        vector<string> a;
        string b, c;
        for (int i = 0; ip[i]; i++) {
            if (ip[i] == '.' || ip[i] == ':') {
                b.push_back(ip[i]);
                a.push_back(c);
                c.clear();
            } else {
                c.push_back(ip[i]);
            }
        }
        a.push_back(c);
        if (b == "...:") {
            int ok = 1;
            LL x = 0;
            for (int i = 0; i < 5; i++) {
                if (a[i].size() == 0 || a[i][0] == '0' && a[i].size() > 1) ok = 0;
                LL y = 0;
                for (auto t : a[i]) {
                    y = y * 10 + t - '0';
                }
                if (i == 4) {
                    if (y >= 65536) ok = 0;
                    x = x * 65536 + y;
                } else {
                    if (y >= 256) ok = 0;
                    x = x * 256 + y;
                }
            }
            if (ok) {
                if (s[0] == 'S') {
                    if (mp[x] == 0) {
                        mp[x] = u;
                        puts("OK");
                    } else {
                        puts("FAIL");
                    }
                } else {
                    if (mp[x] == 0) {
                        puts("FAIL");
                    } else {
                        printf("%d\n", mp[x]);
                    }
                }
            } else {
                puts("ERR");
            }
        } else {
            puts("ERR");
        }
    }
    return 0;
}

小熊的果篮

又是一道模拟题,非常裸的用双向链表维护一下上一个编号和下一个编号,然后每次取出一个水果就是链表的删除操作。还需要用一个vector维护每个块的起始位置

int a[N], L[N], R[N];

int main() {
    int n;
    scanf("%d", &n);
    vector<int> b;
    for (int i = 1; i <= n; i++) {
        scanf("%d", &a[i]);
        if (i == 1 || a[i] != a[i - 1]) b.push_back(i);
        L[i] = i - 1;
        R[i] = i + 1;
    }
    R[0] = 1, L[n + 1] = n;
    a[0] = a[n + 1] = -1;
    while (R[0] != n + 1) {
        vector<int> c;
        for (auto u : b) {
            printf("%d ", u);
            int x = L[u], y = R[u];
            R[x] = y, L[y] = x;
            if (a[u] == a[y] && a[u] != a[x]) c.push_back(y);
        }
        puts("");
        swap(b, c);
    }
    return 0;
}

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

郭晋龙

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值