luogu 十一 基本套路 day1

P3406 海底高铁

一个重要的推论:

对于一个线段,要不就只买票,要不就用IC卡(贪心嘛)

所以只要比较这两种策略,取较大值就好。

rep(i,1,n-1){
        cf[i]+=cf[i-1];
        int cnt=cf[i];
        rd(a[i]),rd(b[i]),rd(c[i]);
//      int cnt=query(i);
        if(cnt*b[i]+c[i]<cnt*a[i])
            ans+= cnt*b[i]+c[i];
        else ans+=cnt*a[i];
    }

对线段进行差分:

就不用再右端点+1的位置--,

而是直接再右端点的位置--;

  • 原理:线段的个数是端点个数-1
rep(i,1,m-1){
        if(p[i]<p[i+1])
            cf[p[i]]++,cf[p[i+1]]--; 
//          add(p[i],1),add(p[i+1],-1);
        else if(p[i]>p[i+1])
            cf[p[i+1]]++,cf[p[i]]--;
//          add(p[i+1],1),add(p[i],-1);
}

【二位前缀和 && 差分】P3397 地毯

rd(n),rd(m);
    while(m--){
        int x1,y1,x2,y2;
        rd(x1),rd(y1),rd(x2),rd(y2);
        cf[x1][y1]++,cf[x2+1][y2+1]++;
        cf[x1][y2+1]--,cf[x2+1][y1]--;
    }
    rep(i,1,n)
        rep(j,1,n){
            sum[i][j]=sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1]+cf[i][j];
        }

P1842 奶牛玩杂技

SOL:

构造相邻的两头牛,看能不能贪心,且看需要满足什么条件的时候才能贪心。
设有相邻的两头牛a,b,来讨论一下在满足什么条件的的情况下a放在b上面比b放在a上面更优:

设放在a,b上面的牛的总重为W

i:a放在b上面
a的压扁值:W-Sa
b的压扁值:W+Wa-Sb

ii:b放在a上面
a的压扁值:W+Wb-Sa
b的压扁值:W-Sb

要使a放在b上面比b放在a上面更优,
则max(W-Sa,W+Wa-Sb,) < max(W+Wb-Sa,W-Sb);
易证W-Sa < W+Wb-Sa,W-Sb<W+Wa-Sb;

那就转化成了使W+Wa-Sb<W+Wb-Sa;
->Wa+Sa < Wb+Sb

综上,当满足这个条件的时候,a放在b上面比b放在a上面更优;

那么我们以Wi+Si为关键字从小到大排序,(此时已经确立各奶牛的位置),那我们从上到下利用前缀和扫一遍最小的压扁值就好啦。

int n,m;
const int N=5e4+10;
struct nainiu{
    int s,w;
    bool operator < (const nainiu &rhs)const{
        return s+w<rhs.s+rhs.w; //贪心 
    }
}cow[N];

#undef int
int main(){
#define int long long
    #ifdef WIN32
    freopen("test.txt","r",stdin);
    #endif
    rd(n);
    rep(i,1,n){
        rd(cow[i].w),rd(cow[i].s);
    }
    sort(cow+1,cow+n+1);
    int sum=0,ans=INT_MIN;
    rep(i,1,n){
        ans=max(ans,sum-cow[i].s);
        sum+=cow[i].w;
    }
    printf("%d",ans);
    return 0; 
}

$x=\frac{a}{b}$

$$ \leq $$

P1223 排队接水

*排序不等式:

易知每个同学的等待时间wait[i]是单调递增的

那么总等待时间就是sigma wait[i] * 自己接水的时间t[i],

根据排序不等式,最小的总等待时间应该是逆序和。

好吧上面在胡扯,这只是一个显然的贪心

P1012 拼数

/*
translation:

设有n个正整数(n≤20),将它们联接成一排,组成一个最大的多位整数。

例如:n=3时,3个整数13,312,343联接成的最大整数为:34331213

solution:
sort 排序字符串是不用加cmp的,自带operator (字典序)//sort对字符串排序只能是c++中string类型

按长度排序加一个a.length就可以了 记住cmp里的条件是return小的条件

note:
字符串排序
date:
2019.07.10
/

string a[25];

bool cmp(string a,string b)
{
    return a+b>b+a;//a+b就是b接在a的后面
}

一些用到了贪心思想的算法

• 哈夫曼编码
• Kruskal求最小生成树
• Dijkstra求单源最短路

P3258 [JLOI2014]松鼠的新家

复习树上点差分

power[u]++,power[v]++;
power[lca(u,v)]--,power[fa[lca(umv)]]--;

debug:

1.打树剖lca的时候return 了深度大的点^^^^^^^^我真是个智娃。

2.不看输出格式,明明1A的……

上一篇:【DP50题】day1


下一篇:【DP五十题】P1736 创意吃鱼法