• NC20282 棘手的操作(启发式合并)


    这道题可以使用启发式合并和延迟的策略来做

    首先我们发现第一个操作就是将两个集合合并,要在合理的复杂度之内做到此事,启发式合并是个好办法

    其次,因为我们需要查询的是最大值,因此用堆来维护也比较方便,但是现在有个问题,因为一些权值会被改变

    而堆不能指定元素删除,因此如果要维护这些值,暴力的做法是把这个值找出来再删掉,这样显然复杂度不过关。

    这里有个思路是延迟删除,给删除的值打标记,表示他被删除了,因为我们求得是最大值,所以当前最大值如果被打标记了,那就跳过这个值继续

    这样得复杂度是过关的。

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    typedef pair<int,int> pll;
    const int N=6e5+10;
    const int mod=998244353;
    struct node{
        priority_queue<int> del,add;
        void ph1(int x){
            add.push(x);
        }
        void ph2(int x){
            del.push(x);
        }
        int top(){
            while(del.size()&&del.top()==add.top())
                del.pop(),add.pop();
            return add.top();
        }
    }s[N],all;
    int p[N],tag[N],alltag;
    int find(int x){
        if(x!=p[x]){
            p[x]=find(p[x]);
        }
        return p[x];
    }
    int a[N];
    vector<int> num[N];
    int main(){
        ios::sync_with_stdio(false);
        int n;
        cin>>n;
        int i;
        for(i=1;i<=n;i++){
            cin>>a[i];
            p[i]=i;
            num[i].push_back(i);
            s[i].ph1(a[i]);
            all.ph1(a[i]);
        }
        int q;
        cin>>q;
        while(q--){
            string opt;
            cin>>opt;
            if(opt=="U"){
                int x,y;
                cin>>x>>y;
                int pa=find(x);
                int pb=find(y);
                if(pa==pb)
                    continue;
                all.ph2(s[pa].top()+tag[pa]);
                all.ph2(s[pb].top()+tag[pb]);
                if(num[pa].size()<num[pb].size()){
                    swap(pa,pb);
                }
                for(auto d:num[pb]){
                    p[d]=pa;
                    a[d]+=tag[pb];
                    a[d]-=tag[pa];
                    s[pa].ph1(a[d]);
                    num[pa].push_back(d);
                }
                all.ph1(s[pa].top()+tag[pa]);
            }
            else if(opt=="A1"){
                int x,v;
                cin>>x>>v;
                int pa=find(x);
                all.ph2(s[pa].top()+tag[pa]);
                s[pa].ph2(a[x]);
                a[x]+=v;
                s[pa].ph1(a[x]);
                all.ph1(s[pa].top()+tag[pa]);
            }
            else if(opt=="A2"){
                int x,v;
                cin>>x>>v;
                int pa=find(x);
                all.ph2(s[pa].top()+tag[pa]);
                tag[pa]+=v;
                all.ph1(s[pa].top()+tag[pa]);
            }
            else if(opt=="A3"){
                int v;
                cin>>v;
                alltag+=v;
            }
            else if(opt=="F1"){
                int x;
                cin>>x;
                int pa=find(x);
                cout<<a[x]+tag[pa]+alltag<<endl;
            }
            else if(opt=="F2"){
                int x;
                cin>>x;
                int pa=find(x);
                cout<<s[pa].top()+tag[pa]+alltag<<endl;
            }
            else if(opt=="F3"){
                cout<<all.top()+alltag<<endl;
            }
        }
        return 0;
    }
    View Code
    没有人不辛苦,只有人不喊疼
  • 相关阅读:
    sql server还原数据库(请选择用于还原的备份集)
    初学K3Cloud开发
    SQL-视图
    2019-07-31 C#基础知识学习
    2019-07-30 C#基础知识学习
    初学数据库
    什么时候该使用SUM()函数
    Mongo Document 校验
    Linux Mysql操作命令
    说一说Unsafe魔法类
  • 原文地址:https://www.cnblogs.com/ctyakwf/p/14609486.html
Copyright © 2020-2023  润新知