NOIP2025模拟赛26

T1 T2 T3 T4
\(\color{#52C41A} 普及+/提高\) \(\color{#3498DB} 提高+/省选-\) \(\color{#9D3DCF} 省选/NOI-\) \(\color{#9D3DCF} 省选/NOI-\)

参赛网址:https://oj.33dai.cn/d/TYOI/contest/68a3e478c5d9c2f14c26c089

这场我的评价是,这场又是 education 场,所以听题解的时候务必认真听哦。

T2,T4未搭建完成

T1 代数几何[2022NOIP模拟赛T1(合并DIV)]

题目传送门

题目难度:\(\color{#52C41A} 普及+/提高\)

算法标签:贪心,其他,构造

思路

我们发现这个题相当于将若干个数分成一个环,然后找环内的乘积最大值。

例:\(n=8,k=2\) 就是将 \(a_0,a_2,a_4,a_6\) 分为一个环,剩下的在另一个组。

然后发现 \(a_0\) 所在的环分别是:\(a_0,a_{0+k},a_{0+2\times k} \dots a_{0+(\alpha-1)\times k}\)

\(0+\alpha\times k \equiv0 \pmod n\) .

然后我们考虑一个特殊情况:

\(\gcd(n,k)=1\),即 \(n\)\(k\) 互质时,\(\alpha\equiv0\pmod n\)

那么我们就可以考虑,设 \(g=\gcd(n,k)\),则 \(k=\beta \times g\),所以 \(0+\alpha\times \beta \times g \equiv0 \pmod n\).

\(\alpha \times g \equiv0 \pmod n\)

\(\alpha = \frac n g\)

所以0所在的环的长度为 \(\frac n {\gcd(n,k)}\)

然后我们发现 \(1+\alpha\times \beta \times g \equiv1 \pmod n\).

所以1所在的环的长度也是 \(\frac n {\gcd(n,k)}\)

然后我们发现一共有 \(\gcd(n,k)\) 个环,每个环的大小为\(\frac n {\gcd(n,k)}\)

特别感谢@Sunpicnic对笔者数学证明方面的帮助,orz.

然后贪心,使用中华传统文化。

我们贪心的去找答案,为了使答案最大,就是最大的数贡献最大,设 \(a\) 是最大值,\(b\) 是次大值,\(c\) 是第三大值,则应 \(ans_{i}=a\)\(ans_{(i+k) mod n}=b\)\(ans_{(i-k+n)mod n}=c\)

AC Code

#include <bits/stdc++.h>
#define int long long
using namespace std;

const int maxn=5005;
int n,m,k;
int a[maxn];

signed main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    cin>>n;
    for (int i=1;i<=n;i++)  cin>>a[i];
    sort(a+1,a+n+1);
    cin>>m;
    while (m--){
        int ans=0;
        cin>>k;
        int g=__gcd(n,k);
        int len=n/g;
        for (int i=1;i+len-1<=n;i+=len){
            int l=i,r=i+len-1;
            int hd=a[l],tl=a[l];
            for (int j=l+1;j<=r;j++){
                if (j%2==1) ans+=hd*a[j],hd=a[j];
                else    ans+=tl*a[j],tl=a[j];
            }
            ans+=hd*tl;
        }
        cout<<ans<<"\n";
    }
    return 0;
}

T2 找环[2022NOIP模拟赛T2(合并DIV)]

题目传送门

题目难度:\(\color{#3498DB} 提高+/省选-\)

算法标签:贪心,倍增,二分

思路

AC Code

T3 维护数组[2022NOIP模拟赛T3(合并DIV)]

题目传送门

题目难度:\(\color{#9D3DCF} 省选/NOI-\)

算法标签:其他,分块,数据结构,线段树,数学

思路

30分:太难了,我不会

https://oj.33dai.cn/d/TYOI/p/N0055/solution

做法1:分块

对于每一块,考虑维护\(a_i\),\(p_i\),\(mx\),\(ans\),分别为原数组,\(max_{j=1}^i a_i\),整块最大值,这个序列的答案。

设块长为 \(b\),则对于每一次的修改操作,直接扫一遍即可,时间复杂度 \(O(b)\)

对于每一次查询:

  • 对于第一个块,对答案的贡献为 \(ans_i\)

  • 对于剩下的块,如果这个块的 \(mx_i \le\) 前面的所有值的最大值,则对答案的贡献为 \(b\times\) 前面的所有值的最大值,否则二分找到小于前面的所有值的最大值,暴力。

最坏时间复杂度 \(O(\frac b n \times log_2 b)\)

总时间复杂度 \(O((\frac b n \times log_2 b+b)m)\)

\(b\) 取800左右的时候比较快。

做法2:兔队线段树

做法3:线段树

AC Code

#include <bits/stdc++.h>
#define int long long
using namespace std;

const int maxn=3e5+5;
int n,Q;
int pos,val;
int siz,cnt;
int a[maxn];
int id[maxn],l[maxn],r[maxn];
int p[maxn],ans[maxn];

void update(int x,int k){
    a[x]=k;
    p[l[id[x]]]=a[l[id[x]]];
    ans[l[id[x]]]=p[l[id[x]]];
    for (int i=l[id[x]]+1;i<=r[id[x]];i++){
        p[i]=max(p[i-1],a[i]);
        ans[i]=ans[i-1]+p[i];
    }
}

int query(){
    int res=0,mx=0;
    for (int i=1;i<=cnt;i++){
        if (p[r[i]]<=mx)    res+=(r[i]-l[i]+1)*mx;
        else if (p[l[i]]>=mx)   res+=ans[r[i]];
        else {
            int x=l[i],y=r[i],po=0;
            while (x<=y){
                int mid=((x+y)>>1);
                if (p[mid]<mx){
                    po=mid;
                    x=mid+1;
                }
                else    y=mid-1;
            }
            if (po>=1)    res+=(po-l[i]+1)*mx;
            res+=(ans[r[i]]-ans[po]);
        }
        mx=max(mx,p[r[i]]);
    }
    return res;
}

signed main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    cin>>n;
    siz=800;
    cnt=n/siz+(n%siz!=0);
    for (int i=1;i<=n;i++){
        cin>>a[i];
        id[i]=(i-1)/siz+1;
    }
    for (int i=1;i<=cnt;i++){
        l[i]=(i-1)*siz+1;
        r[i]=i*siz;
    }
    r[cnt]=n;
    for (int i=1;i<=cnt;i++){
        p[l[i]]=a[i];
        ans[l[i]]=a[i];
        for (int j=l[i]+1;j<=r[i];j++)
            p[j]=max(p[j-1],a[j]),
            ans[j]=ans[j-1]+p[j];
    }
    cin>>Q;
    while (Q--){
        cin>>pos>>val;
        update(pos,val);
        cout<<query()<<"\n";
    }
    return 0;
}

T4 水坑[2022NOIP模拟赛T4(合并DIV)]

题目传送门

题目难度:\(\color{#9D3DCF} 省选/NOI-\)

算法标签:重构树,DP,DFS

posted @ 2025-09-29 19:50  Zzqyoung1121  阅读(11)  评论(0)    收藏  举报