题解:P14118 [SCCPC 2021] Hotpot

题解:P14118 [SCCPC 2021] Hotpot

Part1:

刚入手此题,没仔细看数据范围,就信心满满的打了个暴力,从 \(1\) 循环到 \(m\),每次按照题目描述的进行操作,一个复杂度 \(O(Tm)\) 的暴力就打好了。最后,在 \(m\le10^9\) 的数据下,我毫不意外的 TLE了。

#include<bits/stdc++.h>
using namespace std;
int a[100010],b[100010],c[100010];
int main() {
    int t;
    cin>>t;
    while(t--) {
        int n,k,m;
        cin>>n>>k>>m;
        for(int i=0;i<n;i++) {
            cin>>a[i];
            b[i]=0;
        }
        for(int i=1;i<=k;i++) {
            c[i]=0;
        }
        //暴力模拟操作。
        for(int i=0;i<m;i++) {
            if(c[a[i%n]]<1) {
                c[a[i%n]]++;
            }
            else {
                c[a[i%n]]--;
                b[i%n]++;
            }
            //cout<<a[i%n]<<" "<<c[a[i%n]]<<" "<<i<<" "<<b[i]<<"\n";
        }
        for(int i=0;i<n;i++) {
            cout<<b[i]<<" ";
        }
        cout<<"\n";
    }
    return 0;
}

Part2:

再重新分析题目后,我发现,在 \(m\) 次的操作里,每 \(2\times n\) 次就会发生循环,我抓住了这一点,将这一段代码:

for(int i=0;i<m;i++) {
    if(c[a[i%n]]<1) {
        c[a[i%n]]++;
    }
    else {
        c[a[i%n]]--;
        b[i%n]++;
    }
}

拆分成了三段代码。

  1. 第一段:
for(int i=0;i<2*n;i++) {
    if(c[a[i%n]]<1) {
        c[a[i%n]]++;
    }
    else {
        c[a[i%n]]--;
        b[i%n]++;
    }
}

将操作进行 \(2\times n\) 次,完成其中的一个循环。

  1. 第二段:
for(int i=0;i<n;i++) {
    b[i]*=m/(2*n);
    c[i]*=m/(2*n);
}

将每一个 \(b_i\)\(c_i\) 都乘上总共的周期数。

  1. 第三段:
for(int i=0;i<m%(2*n);i++) {
    if(c[a[i%n]]<1) {
        c[a[i%n]]++;
    }
    else {
        c[a[i%n]]--;
        b[i%n]++;
     }
}

将剩下的操作数补满,完成操作。

这样,我们成功的将 \(O(Tm)\) 优化成了 \(O(T2n)\),通过了这道题。

Part3:

最终代码:

#include<bits/stdc++.h>
using namespace std;
int a[100010],b[100010],c[100010];
int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int t;
    cin>>t;
    while(t--) {
        int n,k,m;
        cin>>n>>k>>m;
        for(int i=0;i<n;i++) {
            cin>>a[i];
            b[i]=0;
        }
        for(int i=1;i<=k;i++) {
            c[i]=0;
        }
        //将操作进行2*n次,完成其中的一个循环。
        for(int i=0;i<2*n;i++) {
            if(c[a[i%n]]<1) {
                c[a[i%n]]++;
            }
            else {
                c[a[i%n]]--;
                b[i%n]++;
            }
        }
        //将每一个b[i]和c[i]都乘上总共的周期数。
        for(int i=0;i<n;i++) {
            b[i]*=m/(2*n);
            c[i]*=m/(2*n);
        }
        //将剩下的操作数补满,完成操作。
        for(int i=0;i<m%(2*n);i++) {
            if(c[a[i%n]]<1) {
                c[a[i%n]]++;
            }
            else {
                c[a[i%n]]--;
                b[i%n]++;
            }
        }
        for(int i=0;i<n;i++) {
            cout<<b[i]<<" ";
        }
        cout<<"\n";
    }
    //完美结束!
    return 0;
}
posted @ 2026-01-11 17:26  Mirror_victor  阅读(0)  评论(0)    收藏  举报