Contest1449 - 2023秋季综合训练(一)(E,G)

问题 E: 兔兔的最小数组
如果你觉得并查集难以理解的话请看此篇

题意:求字典序最小
思路:
比较字典序最小,类似于字符串的比较:只要前面保证最小即可,如:1000大于0111

首先最简单,考虑暴力枚举每个b数组,使得取模后最小,时间复杂度为n^2,(注意:使用后的b数组应该删除)
暴力肯定会wa,所以考虑优化

因为是查找b数组中的值,且可以任意排序,考虑二分优化
查找b数组大于等于(n-a[i])的第一个值
1.如果b数组存在(n-a[i]),优先使用,因为该值取模后为零,字典序肯定最小
2.如果1不满足,则查找第一个大于(n-a[i])的值,因为b数组的值最大为n-1,所以取模后一定小于a[i]
特判
3.如果不存在大于等于(n-a[i])的值,那么使用最小值,这样该位置的值最小

注意:用过的值要删掉(或者过滤,实现方法很多)

如:
1.如果该位置为4,n=7,b数组为 1,4。则b数组选4,最小
2.如果该位置为4,n=7,b数组为 1,2.则b数组选1,最小

ok,到此,思路结束,下面是我的做法

1.利用map存储b数组,map会自己排序
2.利用lower_bound(查找第一个大于等于x的地址)
3.删除用erase

点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+10;
int a[N],b[N];
map<int,int> ma;
int main(){
    // ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    int n;
    cin>>n;
    for(int i=1;i<=n;i++) cin>>a[i];
    for(int i=1;i<=n;i++) {
        cin>>b[i];
        ma[b[i]]++;
    }
    for(int i=1;i<=n;i++){
        auto it=ma.lower_bound(n-a[i]);
        if(it!=ma.end()){//如果能找到,使用该值
            cout<<(a[i]+(*it).first)%n<<' ';
            if(--(it->second)==0) ma.erase(it);
        }
        else{//如果找不到,则使用最小值
            auto id=ma.begin();
            cout<<(a[i]+id->first)%n<<' ';
            if(--(id->second)==0) ma.erase(id);
        }
    }
    return 0;
}

问题 G: 九转数据结构
set的做法,思路跟map一样,但不需要并查集

点击查看代码
#include <bits/stdc++.h>
using namespace std;
const int N=4e5+10;
struct node
{
    mutable int sum;//加mutable可直接修改
    int id;
    node(const int &s, const int &d) : sum(s), id(d) {}//构造函数
    bool operator<(const node &x)const {//自定义比较
        return sum==x.sum?id<x.id:sum<x.sum;
    }
};
int a[N];
set<node> se;
void meger(int l,int r,int k){
    for(auto it=se.lower_bound({l,0});it!=se.end()&&it->sum<=r;++it){
        it->sum=k;//直接修改
        a[(it->id)]=k;
    }
}
int main(){
    ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    int n;
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>a[i];
        se.insert(node(a[i],i));
    }
    int q;
    cin>>q;
    while(q--){
        int op;
        cin>>op;
        if(op==1){
            int k,w;
            cin>>k>>w;
            auto it=se.lower_bound({a[k],0});//找到该点
            it->sum=w;
            a[k]=w;
        }
        else if(op==2){
            int k;
            cin>>k;
            cout<<a[k]<<'\n';
        }
        else{
            int l,r;
            cin>>l>>r;
            int mid=l+r>>1;
            meger(l,mid,l-1);
            meger(mid+1,r,r+1);
        }
    }
    return 0;
}
posted @   不o凡  阅读(17)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示