关于一个trick

trick:动态维护环上相邻点对的值的 \(\max\) 的最大值,然后合并为 \(\max(x,y)\)

用一个 set 维护,一开始先将每个数向前驱和后继分别连一条不同权值的边,然后先初始化前驱后继数组(咋这么像链表),然后开始类似广度优先搜索的跑图(其实一点也不相似,只是结构有点像),然后每次取出最小的,合并后,更新前驱后继即可。

时间复杂度:\(O(n \log n)\),当然带点 STL 的常数。

直接放一道同样 trick 的题目的代码(转化过程详见我的某场比赛的题解的 T3):

#include <bits/stdc++.h>
using namespace std;
const int N = 2e5+5;
int a[N];
int l[N];
int r[N];
int vis[N];
signed main()
{
    ios_base::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    int t;
    cin >> t;
    while(t--)
    {
        int n;
        cin >> n;
        for(int i = 0;i<n;++i)
        {
            cin >> a[i];
            l[i] = (i-1+n)%n;
            r[i] = (i+1)%n;
            vis[i] = 0;
        }
        if(n == 1)
        {
            cout << 0 << '\n';
            continue;
        }
        set<pair<int,int>>s;
        for(int i = 0;i<n;++i)
        {
            s.insert({max(a[i],a[r[i]]),i});
        }
        long long sum = 0;
        int x = n;
        while(x>1)
        {
            auto it = s.begin();
            int cnt = it->first;
            int i = it->second;
            s.erase(it);
            int j = r[i];
            if(vis[i]||vis[j]||r[i]!=j)
            {
                continue;
            }
            sum+=cnt;
            if(a[i]>a[j])
            {
                vis[j] = 1;
                r[i] = r[j];
                l[r[j]] = i;
                s.erase({max(a[l[j]],a[j]),l[j]});
                s.erase({max(a[j],a[r[j]]),j});
                s.insert({max(a[i],a[r[i]]),i});
                s.insert({max(a[l[i]],a[i]),l[i]});
            }
            else
            {
                vis[i] = 1;
                l[j] = l[i];
                r[l[i]] = j;
                s.erase({max(a[l[i]],a[i]),l[i]});
                s.erase({max(a[i],a[r[i]]),i});
                s.insert({max(a[j],a[r[j]]),j});
                s.insert({max(a[l[j]],a[j]),l[j]});
            }
            --x;
        }
        cout << sum << '\n';
    }
    return 0;
}

posted @ 2025-12-09 16:54  林晋堃  阅读(2)  评论(0)    收藏  举报