贪心构造专题

CF1530D Secret Santa

给你一个序列 a,满足 aii,每次操作可以将任意位置上的数改为 [1,n] 上的数,求将此序列变为一个 1n 的排列且 aii 的最小操作次数,输出一种方案。

n2×105

贪心构造,首先次数很简单,就把所有不合法的位置搞掉即可。对于不合法的位置,将可以填上去的数集 S 倒序放在每个位置上,然后依次检查每个位置,若出现 ai=i 的情况,就和同类型的,第一个未修改的位置交换,可以保证合法。时间复杂度 O(nlogn)

code
#include<bits/stdc++.h>
using namespace std;
const int maxn=2e5+3;
int T,n,a[maxn],siz[maxn],vis[maxn];
vector<int>v[maxn];
vector<int>t1,s;
int r1[maxn];
void solve(){
    cin>>n;
    for(int i=1;i<=n;i++){
        vis[i]=0;
        cin>>a[i];
        siz[a[i]]++;
        v[a[i]].emplace_back(i);
    }
    for(int i=1;i<=n;i++){
        if(siz[i]){
            vis[i]=1;
            if(siz[i]>1){
                for(int j=1;j<siz[i];j++){
                    t1.emplace_back(v[i][j]);
                }
                r1[v[i][0]]=i;
            }else{
                if(v[i][0]==i){
                    t1.emplace_back(v[i][0]);
                }else{
                    r1[v[i][0]]=i;
                }
            }
        }
    }
    sort(t1.begin(),t1.end());
    for(int i=1;i<=n;i++){
        if(!vis[i]){
            s.emplace_back(i);
        }
    }
    int len=s.size();
    for(int i=0;i<len;i++){
        r1[t1[i]]=s[len-i-1];
    }
    int f1=0;
    for(int i=1;i<=n;i++){
        if(r1[i]==i){
            swap(r1[i],r1[v[a[i]][0]]);
        }
    }
    if(!f1){
        cout<<n-len<<'\n';
        for(int i=1;i<=n;i++){
            cout<<r1[i]<<" \n"[i==n];
        }
    }
    for(int i=1;i<=n;i++){
        v[i].clear();
        siz[i]=0;
        r1[i]=0;
    }
    s.clear();
    t1.clear();
}
signed main(){
    cin>>T;
    while(T--){
        solve();
    }
    return 0;
}

ABC137D Summer Vacation

给你 n 个工作,(ai,bi) 表示工作 i 需要花费 ai 天,收益为 bi,每天只能做一个,求 m 天内得到的最大收益。

n,m105

考虑带悔贪心,先按 ai 为第一关键字,bi 为第二关键字排序,若 mcntai 则把 i 扔进堆里,否则就考虑把堆里最小的元素扔掉直到满足条件,再把 i 放进堆里,每步求最优答案,时间复杂度 O(nlogn)

code
#include<bits/stdc++.h>
using namespace std;
const int maxn=2e5+3;
int n,m;
struct node{
    int a,b;
    bool operator<(const node o)const{
        if(a!=o.a) return a>o.a;
        return b<o.b;
    }
}a[maxn];
struct nodee{
    int a,b;
    bool operator<(const nodee o)const{
        if(b!=o.b) return b>o.b;
        return a>o.a;
    }
};
priority_queue<nodee>q;
int ans,sum,cnt;
signed main(){
    cin>>n>>m;
    for(int i=1;i<=n;i++){
        cin>>a[i].a>>a[i].b;
    }
    sort(a+1,a+n+1);
    for(int i=1;i<=n;i++){
        int tot=0;
        if(m-cnt>=a[i].a){
            q.push({a[i].a,a[i].b});
            cnt++;
            sum+=a[i].b;
            ans=max(ans,sum);
        }else{
            while(!q.empty()&&m-cnt<a[i].a&&tot+q.top().b<=a[i].b){
                tot+=q.top().b;
                sum-=q.top().b;
                cnt--;
                q.pop();
            }
            if(m-cnt>=a[i].a){
                q.push({a[i].a,a[i].b});
                cnt++;
                sum+=a[i].b;
            }
            ans=max(ans,sum);
        }
    }

    cout<<ans<<'\n';
    return 0;
}

P4377 [USACO18OPEN] Talent Show G

给你一序列 (wi,ti),求一种 ci{0,1} 序列,满足 R=citiciwi 最大且分母不小于 W,输出 1000×Rmax

n250,W1000

分数规划板子题。

分数规划具有单调性,于是我们可以二分一个 x,判断 Rx 即合法。拆式子

citicixwici(tixwi)0

满足上式即可,记 di=tixwi。对于没有 W 的限制,可以直接贪心选取 di>0 的位置;而有了 W 的限制,就使用背包,wi 为重量,di 为价值,fW>0 即合法,时间复杂度 O(nWlognW)

code
#include<bits/stdc++.h>
using namespace std;
const int maxn=253;
const double eps=1e-6;
int n,W,a[maxn],b[maxn];
double f[maxn<<3];
bool check(double x){
    for(int i=1;i<=W;i++) f[i]=-1e9;
    for(int i=1;i<=n;i++){
        for(int j=W;j>=0;j--){
            int k=min(W,j+a[i]);
            f[k]=max(f[k],f[j]+b[i]-x*a[i]);
        }
    }
    return f[W]>0;
}
signed main(){
    cin>>n>>W;
    for(int i=1;i<=n;i++){
        cin>>a[i]>>b[i];
    }
    double l=0,r=250000,ans;
    while(l+eps<=r){
        double mid=(l+r)/2;
        if(check(mid)){
            l=mid;
        }else{
            r=mid;
        }
    }
    cout<<int(l*1000);
    return 0;
}
posted @   view3937  阅读(9)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
Title
点击右上角即可分享
微信分享提示