暑假集训Chapter1 贪心

为什么要今天写呢?

明天全力研究Johnson和一些奇奇怪怪的贪心

今天把能写的都写了

T1T2太水了直接上代码吧

#include<bits/stdc++.h>
#define LL long long
using namespace std;
inline int read()
{
    int x=0,f=1;char ch;
    for(ch=getchar();!isdigit(ch);ch=getchar())if(ch=='-')f=-f;
    for(;isdigit(ch);ch=getchar())x=10*x+ch-'0';
    return x*f;
}
int n;
priority_queue<int,vector<int>,greater<int> > q1;
priority_queue<int> q2;
int main()
{
    n = read();int a;
    for(int i=1;i<=n;i++)a = read(),q1.push(a),q2.push(a);
    while(q1.size() >= 2)
    {
        int t1 = q1.top();q1.pop();
        int t2 = q1.top();q1.pop();
        q1.push(t1 * t2 + 1);
    }
    //cout<<q1.top()<<endl;
    while(q2.size() >= 2)
    {
        int t1 = q2.top();q2.pop();
        int t2 = q2.top();q2.pop();
        q2.push(t1 * t2 + 1);
    }
    //cout<<q2.top()<<endl;
    cout<<q1.top() - q2.top();
}
T1
#include<bits/stdc++.h>
#define LL long long
using namespace std;
inline int read()
{
    int x=0,f=1;char ch;
    for(ch=getchar();!isdigit(ch);ch=getchar())if(ch=='-')f=-f;
    for(;isdigit(ch);ch=getchar())x=10*x+ch-'0';
    return x*f;
}
int n,m;
int a[100010];
int main()
{
    n = read(),m = read();int ans = 0,tot = 0;
    for(int i=1;i<=n;i++)
    {
        a[i] = read();
        tot += a[i];
        if(tot > m) tot = a[i],ans++;
    }
    cout<<ans + 1;
}
T2

T3

每个作业有一个学分和一个DDL

在DDL前完成作业可以获得相应的学分

给出每个作业的学分和DDL

求一个顺序使得学分最大

每做一项作业需要一整天

首先 比起一天浪费掉做已经达到DDL的事情

还不如用它来拿学分

于是我们把task按DDL排序

用一个数据结构变量来记录当前选了几个task

如果可以继续选task就选

选不了就找一个分最少的和当前的比一比取大的就行了

人类智慧

#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
#include<vector>
#include<algorithm>
#define LL long long
#define pii pair<int,int>
#define x(a) a.first
#define y(a) a.second
using namespace std;
inline int read()
{
    int x=0,f=1;char ch;
    for(ch=getchar();!isdigit(ch);ch=getchar())if(ch=='-')f=-f;
    for(;isdigit(ch);ch=getchar())x=10*x+ch-'0';
    return x*f;
}
int n,now;
bool cmp(pii a,pii b){return y(a) < y(b);}
int main()
{
    while(cin>>n)
    {
        now = 0;
        if(n == 0){puts("0");continue;}
        priority_queue<pii,vector<pii>,greater<pii> > q;
        pii s[100010];
        int ans = 0;
        for(int i=1;i<=n;i++)
        {
            x(s[i]) = read();
            y(s[i]) = read();
        }
        sort(s + 1,s + n + 1,cmp);
        for(int i=1;i<=n;i++)
        {
            pii temp = s[i];
            if(now < y(temp))
            {
                ++now;
                q.push(temp);
                ans += x(temp);
            }
            else
            {
                pii tmp = q.top();q.pop();
                if(x(temp) > x(tmp)){q.push(temp);ans += x(temp);ans -= x(tmp);}
                else q.push(tmp);
            }
        }
        cout<<ans<<endl;
    }
}
View Code

poj1042钓鱼

(fish is me

话说发源于小朋友精心设计的游戏被电脑组的童鞋们藐杀之后非常不爽,为了表示安慰和鼓励,VIP999决定请他吃一次“年年大丰收”,为了表示诚意,他还决定亲自去钓鱼,但是,因为还要准备2013NOIP,z老师只给了他H(1<=H<=16)个小时的空余时间,假设有N(2<=n<=25)个鱼塘都在一条水平路边,从左边到右编号为1、2、3、。。。、n)。VIP是个很讲究效率的孩子,他希望用这些时间钓到尽量多的鱼。他从湖1出发,向右走,有选择的在一些湖边停留一定的时间钓鱼,最后在某一个湖边结束钓鱼。他测出从第I个湖到I+1个湖需要走5*ti分钟的路,还测出在第I个湖边停留,第一个5分钟可以钓到鱼fi,以后再每钓5分钟鱼,鱼量减少di。为了简化问题,他假定没有其他人钓鱼,也不会有其他因素影响他钓到期望数量的鱼。请编程求出能钓最多鱼的数量。 

大暴力

枚举这个人最后走到的湖

把路上的时间减去

每5分钟选择鱼最多的地方钓

#include<bits/stdc++.h>
using namespace std;
inline int read()
{
    int x = 0,f = 1;char ch = getchar();
    for(;!isdigit(ch);ch = getchar())if(ch == '-')f = -f;
    for(;isdigit(ch);ch = getchar())x = 10 * x + ch - '0';
    return x * f;
}
int n,h;
struct abcd
{
    int fish,d,t;
    bool operator < (const abcd &b)const
    {
        return fish < b.fish;
    }
}a[100010];
priority_queue<abcd> q;

int main()
{
    int res = 0;
    n = read();h = read() * 12;
    for(int i=1;i<=n;i++)a[i].fish = read();
    for(int i=1;i<=n;i++)a[i].d = read();
    for(int i=1;i<n;i++)a[i].t = read();
    for(int rt=1;rt<=n;rt++)
    {
        int temp = 0;
        while(!q.empty())q.pop();
        int cur = h;
        for(int i=1;i<=rt;i++)q.push(a[i]);
        for(int i=1;i<rt;i++)cur -= a[i].t;
        while(cur > 0 && !q.empty())
        {
            abcd now = q.top();q.pop();
            if(now.fish < 0)break;
            temp += now.fish;now.fish -= now.d;
            if(now.fish > 0)q.push(now);
            cur--;
        }
        res = max(res,temp);
    }
    cout<<res;
}
View Code

环状均分纸牌

选择中位数作为起点

然后用f[i]表示要挪到i+1处的纸牌数量

那么f[i] = k - a[i] + f[i - 1]

sigma fi就是答案

#include<bits/stdc++.h>
using namespace std;
inline int read()
{
    int x = 0,f = 1;char ch = getchar();
    for(;!isdigit(ch);ch = getchar())if(ch == '-')f = -f;
    for(;isdigit(ch);ch = getchar())x = 10 * x + ch - '0';
    return x * f;
}
int n,avg;
int a[100010],p[100010];
int main()
{
    n = read();
    for(int i=1;i<=n;i++)a[i] = read(),avg += a[i];
    avg /= n;
    for(int i=1;i<=n;i++)p[i] = avg - a[i] + p[i - 1];
    sort(p + 1,p + n + 1);
    int mid = p[n / 2 + 1],ans = 0;
    for(int i=1;i<=n;i++)ans += abs(p[i] - mid);
    cout<<ans;
}
View Code
原文地址:https://www.cnblogs.com/Kong-Ruo/p/9278391.html