反悔贪心小结

· · 个人记录

前言

正文

或者

总结套路

  1. 建模
  2. 找增广路
  3. 将当前状态分类
  4. 根据状态将增广路具体为改变种类的操作

需要注意的是,这只是一类反悔贪心,博大精深的反悔贪心并不是能够以偏概全的,还需具体情况具体分析!!!

代码举例

主要对照上文的伪代码看代码格式

CF436E

#include<bits/stdc++.h>
#define fi first
#define se second
#define mp make_pair
#define rep(i,l,r) for(int i(l),i##end(r);i<=i##end;++i)
using namespace std;
typedef long long ll;
typedef pair<ll,int> pii;
const int N = 3e5 + 9;
const ll INF = 0x3f3f3f3f3f3fLL;
int n,w;
int a[N],b[N],vis[N];
ll val1,val2,val3,val4,ans;
priority_queue<pii,vector<pii>,greater<pii> > q01,q02,q12,q10,q21;
void In(int i) {
    if(vis[i]==0) q01.push(mp(a[i],i)),q02.push(mp(b[i],i));
    if(vis[i]==1) q12.push(mp(b[i]-a[i],i)),q10.push(mp(-a[i],i));
    if(vis[i]==2) q21.push(mp(a[i]-b[i],i));
}
main() {
    scanf("%d%d",&n,&w);
    rep(i,1,n) scanf("%d%d",&a[i],&b[i]);
    rep(i,1,n) In(i);
    vis[n+1]=0;
    vis[n+2]=1;
    vis[n+3]=2;
    q01.push(mp(INF,n+1)); q02.push(mp(INF,n+1));
    q10.push(mp(INF,n+2)); q12.push(mp(INF,n+2)); 
    q21.push(mp(INF,n+3)); 
    rep(i,1,w) {
        while(vis[q01.top().se]!=0) q01.pop();
        while(vis[q02.top().se]!=0) q02.pop();
        while(vis[q12.top().se]!=1) q12.pop();
        while(vis[q10.top().se]!=1) q10.pop();
        while(vis[q21.top().se]!=2) q21.pop();
        val1=q01.top().fi;
        val2=q12.top().fi;
        val3=q21.top().fi+q02.top().fi;
        val4=q10.top().fi+q02.top().fi;
        ll minn=min(min(val1,val2),min(val3,val4));
        ans+=minn;
        if(val1==minn) {
            vis[q01.top().se]=1; In(q01.top().se);
            continue;
        }
        if(val2==minn) {
            vis[q12.top().se]=2; In(q12.top().se);
            continue;
        }
        if(val3==minn) {
            vis[q21.top().se]=1; In(q21.top().se);
            vis[q02.top().se]=2; In(q02.top().se);
            continue;
        }
        if(val4==minn) {
            vis[q10.top().se]=0; In(q10.top().se);
            vis[q02.top().se]=2; In(q02.top().se);
            continue;
        }
    }
    printf("%lld\n",ans);
    rep(i,1,n) printf("%d",vis[i]);
    return 0;
}

Luogu P5470

#include<bits/stdc++.h>
#define fi first
#define se second
#define mp make_pair
#define rep(i,l,r) for(int i(l),i##end(r);i<=i##end;++i)
using namespace std;
typedef long long ll;
typedef pair<ll,int> pli;
const int N = 2e5 + 9;
const ll INF = 0x3f3f3f3f3f3fLL;
int T,n,K,L,cnt;
int a[N],b[N],vis[N],oa[N],ob[N];//0 none,1 a,2 b,3 ab
ll ans,sum0,sum1,sum2,sum3,maxn;
priority_queue<pli> q03,q10,q13,q20,q23,q30;
bool cmpa(int u,int v) {return a[u]>a[v];}
bool cmpb(int u,int v) {return b[u]>b[v];}
void In(int i) {
    if(vis[i]==0) q03.push(mp(a[i]+b[i],i));
    if(vis[i]==1) q10.push(mp(-a[i],i)),q13.push(mp(b[i],i));
    if(vis[i]==2) q20.push(mp(-b[i],i)),q23.push(mp(a[i],i));
    if(vis[i]==3) q30.push(mp(-a[i]-b[i],i));
}
main() {
    // freopen("a.in","r",stdin);
    scanf("%d",&T);
    while(T--) {
        while(!q03.empty()) q03.pop();
        while(!q10.empty()) q10.pop();
        while(!q13.empty()) q13.pop();
        while(!q20.empty()) q20.pop();
        while(!q23.empty()) q23.pop();
        while(!q30.empty()) q30.pop();
        scanf("%d%d%d",&n,&K,&L);
        rep(i,1,n) scanf("%d",&a[i]);
        rep(i,1,n) scanf("%d",&b[i]);
        rep(i,1,n) oa[i]=i,ob[i]=i;
        sort(oa+1,oa+n+1,cmpa);
        sort(ob+1,ob+n+1,cmpb);
        rep(i,1,n) vis[i]=0;
        ans=0;
        rep(i,1,K) vis[oa[i]]|=1,ans+=a[oa[i]];
        rep(i,1,K) vis[ob[i]]|=2,ans+=b[ob[i]];
        vis[n+1]=0;
        vis[n+2]=1;
        vis[n+3]=2;
        vis[n+4]=3;
        q03.push(mp(-INF,n+1));
        q10.push(mp(-INF,n+2)),q13.push(mp(-INF,n+2));
        q20.push(mp(-INF,n+3)),q23.push(mp(-INF,n+3));
        q30.push(mp(-INF,n+4));
        rep(i,1,n) In(i);
        cnt=0;
        rep(i,1,n) if(vis[i]==3) ++cnt;
        rep(i,cnt+1,L) {
            while(vis[q03.top().se]!=0) q03.pop();
            while(vis[q10.top().se]!=1) q10.pop();
            while(vis[q13.top().se]!=1) q13.pop();
            while(vis[q20.top().se]!=2) q20.pop();
            while(vis[q23.top().se]!=2) q23.pop();
            while(vis[q30.top().se]!=3) q30.pop();
            sum0=q23.top().fi+q10.top().fi;
            sum1=q13.top().fi+q20.top().fi;
            sum2=q10.top().fi+q20.top().fi+q03.top().fi;
            sum3=q13.top().fi+q23.top().fi+q30.top().fi;
            maxn=max(max(sum0,sum1),max(sum2,sum3));
            ans+=maxn;
            if(maxn==sum0) {
                vis[q23.top().se]=3; In(q23.top().se);
                vis[q10.top().se]=0; In(q10.top().se);
                continue;
            }
            if(maxn==sum1) {
                vis[q13.top().se]=3; In(q13.top().se);
                vis[q20.top().se]=0; In(q20.top().se);
                continue;
            }
            if(maxn==sum2) {
                vis[q10.top().se]=0; In(q10.top().se);
                vis[q20.top().se]=0; In(q20.top().se);
                vis[q03.top().se]=3; In(q03.top().se);
                continue;
            }
            if(maxn==sum3) {
                vis[q13.top().se]=3; In(q13.top().se);
                vis[q23.top().se]=3; In(q23.top().se);
                vis[q30.top().se]=0; In(q30.top().se);
                continue;
            }
        }
        printf("%lld\n",ans);
    }
    return 0;
}

致谢名单

@WAPER4EVER 你在P5470的题解里的说法很具有启发性

@s_r_f 你在P5470的题解里的说法很具有启发性

@lyyi2003 你在CF436E的题解里的说法很具有启发性

还有一些,因为时间的问题,不记得了,抱歉。