1 2025 02 07 模拟赛总结

写于2025年2月9日

成绩表

依旧是被TZK大神爆杀的一天
![[photo/Pasted image 20250209163626.png]]

做题情况

  • T1:签到题,没什么好说的(100)
  • T2:以为自己是正解,但只拿到30pts,正解要复杂一些(30)
  • T3:实际上这题比较简单、可做,但赛场上没什么自信(时间)去想正解,于是直接打了暴力(30)
  • T4:子区间颜色数和的问题,不会做,赛后看题解也没有看懂,等以后学了莫队回来补(30)

赛时心态

感觉比赛时有些紧张,但还好,因为是模拟赛,而且第一题是一个签到题,看了一眼就知道怎么做了。在做第二题时遇到了困难,因为题面以及样例解释都给错了,导致卡了一段时间,最后想出了自己以为是正解的解法。所以做第二题时稍微有点慌。T3、T4因为之前从来没有做出来过,所以看了一眼没有思路就直接开始打暴力。最后T4的暴力差点没写出来,那时候是真慌了,差点放弃。

总结

优点

会的题都做对了,不会的题也打了暴力,拿到了暴力分,没有放弃打T4的暴力

缺点

做题经验不足,T2和T3其实是有机会想出来的,但是缺乏经验,做T3时心态有些急躁了(或者说没有信心做T3),因而没有敢去想正解

题面及题解

T1

![[photo/Pasted image 20250209165521.png]]
没什么好说的,直接看AC代码

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>

using namespace std;

const int N = 1e5 + 10;

int n;
int h[N], ver[N << 1], ne[N << 1], tot;
int siz[N], ans1[N], ans2[N];
void add(int x, int y){
	ver[++tot] = y;
	ne[tot] = h[x];
	h[x] = tot;
}
void dfs(int x, int fa){
	siz[x] = 1;
	ans1[x] = ans1[fa] + 1; 
	for(int i = h[x]; i; i = ne[i]){
		int y = ver[i];
		if(y == fa) continue;
		dfs(y, x);
		siz[x] += siz[y];
	}
}
int main(){
	scanf("%d", &n);
	for(int i = 1; i < n; i++){
		int x, y;
		scanf("%d%d", &x, &y);
		add(x, y);
		add(y, x);
	}	
	dfs(1, 0);
	for(int i = 1; i <= n; i++){
		printf("%d %d\n", ans1[i], n - siz[i] + 1);
	}
	return 0;
}

T2

原题:Problem - I - Codeforces
赛时题面太抽象
给定一个长度为n的正整数序列,定义一个区间的权值为区间内出现的不同数字的数量减去区间mex,一个区间的mex为这个区间内最小的没有出现过的正整数。你需要选出一个非空子区间使得权值最大。
样例:
![[photo/Pasted image 20250209170135.png]]
大致思路:枚举可能的mex,根据mex将原序列分段,然后在这些分开的段中找出不同数字数目最多的减去mex,ans再和它取最大即可。
ACcode:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>

#define ll long long
using namespace std;

const int N = 2e5 + 10, inf = 1 << 29;

int n, m;
int a[N], t[N], v[N];
vector<vector<int>> dic(N);
struct que{
    int l, r, mex;
    bool operator < (const que &o) const { return r < o.r; }
};
vector<que> ask;
int read(){
    int ret = 0, f = 1;
    char c = getchar();
    while(c < '0' || c > '9'){
        if(c == '-') f = -1;
        c = getchar();
    }
    while(c >= '0' && c <= '9'){
        ret = ret * 10 + c - '0';
        c = getchar();
    }
    return ret * f;
}

void modify(int x, int d){
    for(; x <= n; x += x & -x) t[x] += d;
}
int query(int x){
    int ret = 0;
    for(; x > 0; x -= x & -x) ret += t[x];
    return ret;
}

int main(){
    //freopen("test.in","r",stdin);

    n = read(), m = read();

    for(int i = 1; i <= n; i++){
        a[i] = read();
        if(a[i] <= n) dic[a[i]].push_back(i);
    }  
    int cnt = 0;
    for(int i = 1; i <= n + 1; i++){
        if(dic[i].size()){
            int pre = 1;
            for(auto r : dic[i]){
                if(r - 1 >= pre){
                    ask.push_back({pre, r - 1, i});
                }
                pre = r + 1;
            }
            if(pre <= n){
                ask.push_back({pre, n, i});
            }
        } else {
            ask.push_back({1, n, i});
            break;
        }
    }
    sort(ask.begin(), ask.end());
    int lal = 1;
    int ans = -inf;
    for(auto [l, r, mex] : ask){
        for(int j = lal; j <= r; j++){
            if(v[a[j]]) modify(v[a[j]], -1);
            v[a[j]] = j;
            modify(j, 1);
        }
        lal = r + 1;
        ans = max(query(r) - query(l - 1) - mex, ans);
    }
    printf("%d\n",ans);


    
    return 0;
}

T3

原题:Problem - I - Codeforces
![[photo/Pasted image 20250209170605.png]]
这个题感觉根本没有我想象中T3的难度,但赛时感觉很难。
考虑\(a_i > a_{i+1}\),那么i后面必须被划分开。这也就意味着所有的漂亮划分的k都是i的因子。
所以使用一个线段树维护所有\(a_i > a_{i+1}\)​位置的i,求它们的最大公因数,答案就是最大公因数的因数数量。直接用线段树维护一个区间gcd即可,注意gcd = 0的情况,某人因为这一点挂了100
ACcode:

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<cstdlib>

using namespace std;

const int N = 1e5 + 10;

int T, n, m;
int a[N], cnt[N];
struct node{
    int l, r, dat;
}t[N << 2];

int read(){
    int ret = 0, f = 1;
    char c = getchar();
    while(c < '0' || c > '9'){
        if(c == '-') f = -1;
        c = getchar();
    }
    while(c >= '0' && c <= '9'){
        ret = ret * 10 + c - '0';
        c = getchar();
    }
    return ret * f;
}

void calc(){
    for(int i = 1; i <= N - 10; i++){
        for(int j = i; j <= N - 10; j += i){
            cnt[j]++;
        }
    }
}

int gcd(int a, int b){
    return b == 0 ? a : gcd(b, a % b);
}

void build(int p, int l, int r){
    t[p].l = l, t[p].r = r;
    if(l == r){
        t[p].dat = (a[l] > a[l + 1] && l < n) ? l : 0;
        return;
    }
    int mid = l + r >> 1;
    build(p << 1, l, mid);
    build(p << 1 | 1, mid + 1, r);
    t[p].dat = gcd(t[p << 1].dat, t[p << 1 | 1].dat);
}

void modify(int p, int l, int r, int x, int v){
    if(l == r){
        t[p].dat = v;
        return;
    }
    int mid = l + r >> 1;
    if(x <= mid) modify(p << 1, l, mid, x, v);
    else modify(p << 1 | 1, mid + 1, r, x, v);
    t[p].dat = gcd(t[p << 1].dat, t[p << 1 | 1].dat);
}


void solve(){

    n = read(), m = read();
    cnt[0] = n;
    for(int i = 1; i <= n; i++) a[i] = read();
    
    build(1, 1, n);

    printf("%d\n", cnt[t[1].dat]);
    //printf("t[1].dat: %d\n", t[1].dat);

    for(int i = 1; i <= m; i++){
        int x = read(), v = read();
        a[x] = v;
        if(x > 1){
            modify(1, 1, n, x - 1, (a[x - 1] > a[x] ? x - 1 : 0));
        } 
        if(x < n){
            modify(1, 1, n, x, (a[x] > a[x + 1] ? x : 0));
        }
        printf("%d\n", cnt[t[1].dat]);
        //printf("t[1].dat: %d\n", t[1].dat);
    } 


}

int main(){
    //freopen("test.in","r",stdin);

    calc();
    int T = 1;
    while(T--){
        solve();
    }
}

T4

原题:Dashboard - 2023 Xian Jiaotong University Programming Contest - Codeforces(J题,但是打不开)
![[photo/Pasted image 20250209171334.png]]

![[photo/Pasted image 20250209171727.png]]

ACcode(莫队,网上的,我没写):


#include "bits/stdc++.h"

using namespace std;
using i64 = long long;
using u32 = unsigned int;

constexpr int N = 2E6;
int cnt[N + 1];

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int n, m;
    cin >> n >> m;

    vector<int> a(n);
    for (int i = 0; i < n; i++) {
        cin >> a[i];
        a[i]--;
    }

    vector<int> p(n, -1);
    vector<int> pre(n, -1);
    for (int i = 0; i < n; i++) {
        pre[i] = p[a[i]];
        p[a[i]] = i;
    }

    p.assign(n, n);
    vector<int> nex(n, n);
    for (int i = n - 1; i >= 0; i--) {
        nex[i] = p[a[i]];
        p[a[i]] = i;
    }

    struct node {
        int l, r, id;
    };
    vector<node> q(m);
    for (int i = 0; i < m; i++) {
        int l, r;
        cin >> l >> r;
        l--, r--;
        q[i] = { l, r, i };
    }

    int bk = sqrt(m);
    sort(q.begin(), q.end(), [&](node a, node b) {
        return ((a.l / bk) ^ (b.l / bk)) ? a.l < b.l : (((a.l / bk) & 1) ? a.r < b.r : a.r > b.r);
    });

    int l = 0, r = -1;
    u32 res = 0;
    u32 Lres = 0, Rres = 0;
    u32 Cnt = 0;

    vector<u32> ans(m);
    auto add = [&](int pos, bool flag) {
        int num = a[pos];
        ++cnt[num];
        if (cnt[num] == 1) {
            ++Cnt;
        }
        if (flag) {
            Rres += pos - max(pre[pos], l - 1);
            res += Rres;
            Lres += Cnt;
        } else {
            Lres += min(r, nex[pos] - 1) - pos + 1;
            res += Lres;
            Rres += Cnt;
        }
    };
    auto del = [&](int pos, bool flag) {
        int num = a[pos];
        if (flag) {
            res -= Rres;
            Lres -= Cnt;
            Rres -= pos - max(pre[pos], l - 1);
        } else {
            res -= Lres;
            Rres -= Cnt;
            Lres -= min(r, nex[pos] - 1) - pos + 1;
        }
        --cnt[num];
        if (cnt[num] == 0) {
            --Cnt;
        }
    };

    for (int i = 0; i < m; i++) {
        auto &[ql, qr, qid] = q[i];
        while (r < qr) add(++r, 1);
        while (l > ql) add(--l, 0);
        while (l < ql) del(l++, 0);
        while (r > qr) del(r--, 1);
        ans[qid] = res;
    }

    for (int i = 0; i < m; i++) {
        cout << ans[i] << '\n';
    }
    return 0;
}
posted @ 2025-10-05 17:55  michaele  阅读(6)  评论(0)    收藏  举报