2019.6.10 一场毒瘤的考试【including 入门OJ·poker,工业时代

初见安~这次卡过了200的门槛!立个Flag!

Poker

传送门:入门OJ P2046

Description

一副扑克牌有n张牌。一般你买的一副新扑克牌里除了这n张牌外还会有一些张特殊的牌,如
果你不小心弄丢了n张牌中的某一张,就可以用特殊牌来代替,但是如果你弄丢两张的话就
没有办法了,因为特殊牌上的图案是一样的。
现在你得到了很多扑克牌,准确来说,n种牌你各有a1、a2、……、an张,同时你还有b张特
殊牌,现在你需要从这些牌中整理出若干副牌供大家使用。整理出的一副牌可以由n种普通
牌各一张组成,也可以由n-1种普通牌各一张再加一张特殊牌组成。
请你设计出一种方案,整理出尽可能多的牌。

Input

输入包括2行
第一行给出n和b1
第二行给出a1,a2…an。
1<=n<=1000000牌的数量<=10^6

Output

输出最多能整理出的牌的副数。

Sample Input

5 5
5 5 5 5 5 

Sample Output

6

Sol

这个题其实第一反应是很懵的……感觉是个贪心,但是如果一开始就先把能凑起来的都凑起来似乎也不对。所以给样例点个赞!!!提醒了我们一件事——特殊牌的作用不应该为当有牌不够的时候才用上,而是能用就用,用来省牌以多凑几副,因为每一副牌只能用一次特殊牌

所以贪心的思路就有了——每次都选牌数最少的一种牌发一张特殊牌,尽量把牌用完。如果出现了两种牌同时缺牌的情况,那就break;如果特殊牌用完了,但是最少的牌还能继续凑,那就继续。

思路就这么简单,具体实现的话这里因为优先队列常数太大怕TLE就很愚蠢地写了个 线段树来维护……【至少本机测数据等给我的感觉是线段树更快】并且每发一张牌,并不是所有牌直接数量减一,而是仅仅让被发的牌数量加一,判断维护的牌数减去当前轮数【也就是每种牌已经用掉的牌数】是否出现了两次为0即可break;而特殊牌用完后,我们已经进行了b轮;最少的牌首先也要减去b,才是剩下的可以用的牌数,所以化简一下直接输出即可。

#include<bits/stdc++.h>
#define maxn 1000005
using namespace std;
int read()
{
    int x = 0, f = 1, ch = getchar();
    while(!isdigit(ch)) {if(ch == '-') f = -1; ch = getchar();}
    while(isdigit(ch)) x = (x << 1) + (x << 3) + ch - '0', ch = getchar();
    return x * f;
}
 
int n, b;
struct node
{
    int num, x;
    bool operator < (const node &tmp) const {return x < tmp.x;}
}minn[maxn << 2];
 
void build(int p, int l, int r)
{
    if(l == r) {minn[p].x = read(), minn[p].num = l; return;}
    register int mid = l + r >> 1;
    build(p << 1, l, mid);
    build(p << 1 | 1, mid + 1, r);
    minn[p] = min(minn[p << 1], minn[p << 1 | 1]);
}
 
void change(int p, int l, int r, int x)
{
    if(l == r) {minn[p].x++; return;}
    register int mid = l + r >> 1;
    if(x <= mid) change(p << 1, l, mid, x);
    else change(p << 1 | 1, mid + 1, r, x);
    minn[p] = min(minn[p << 1], minn[p << 1 | 1]);
}
 
signed main()
{
//  freopen("in.txt", "r", stdin);
    n = read(), b = read();
    build(1, 1, n);//关于线段树……
    register int tmp1, tmp2, i;
    for(i = 1; i <= b; i++)
    {
        tmp1 = minn[1].x; tmp2 = minn[1].num;//还要记录是第几个
        change(1, 1, n, tmp2);//修改
        if(minn[1].x == i) break;//如果==i,就相当于仍有一个牌用完了的,break了
    }
    printf("%d\n", minn[1].x);
    return 0;
}

就这样。

工业时代

传送门:入门OJ P6216

Description

小FF的第一片矿区已经开始运作了, 他着手开展第二片矿区……小FF的第二片矿区, 也是"NewBe_One"计划的核
心部分, 因为在这片矿区里面有全宇宙最稀有的两种矿物,科学家称其为NEW矿和BE矿。矿区是被划分成一个n*m
的矩形区域。 小FF探明了每一小块区域里的NEW矿和BE矿的蕴藏量, 并且小FF还在矿区的北边和西边分别设置了N
EW矿和BE矿的收集站。你的任务是设计一个管道运输系统,使得运送的NEW矿和BE矿的总量最多。管道的型号有两
种,一种是东西向,一种是南北向。在一个格子内你能建造一种管道,但不能两种都建。如果两个同类型管道首位
相接,它们就可以被连接起来。另外这些矿物都十分不稳定,因此它们在运送过程中都不能拐弯。这就意味着如果
某个格子上建有南北向管道,但是它北边的格子建有东西向管道,那么这根南北向管道内运送的任何东西都将丢失
。进一步地,运到NEW矿收集站的BE矿也会丢失,运到BE矿收集站的NEW矿也会丢失。

Input

第一行包含两个整数n和m,表示矿区大小。
以下n行,每行m个整数,其中第i行第j个整数G[ i , j ] 描述各个格子上的BE矿数量。
接下来以类似的矩阵表示各个格子上的NEW矿数量。
0<= n, m <=1000;   
0<= G[ i, j ] <=1000.

Output

 仅一个整数, 表示最多可以采集到的NEW矿和BE矿的总量。

Sample Input

4 4
0 0 10 9
1 3 10 0
4 2 1 3
1 1 20 0
10 0 0 0
1 1 1 30
0 0 5 5
5 10 10 10

Sample Output

98

Sol

一看就是一个dp题。但是考试的时候我想复杂了……还一横一竖地考虑……忽略了一个很关键的信息——对于有意义的一行,一定是左边一部分向左,右边一部分向上。这样的话,只要上一行的状态满足向上的包含了当前状态的向上的部分,就是可以直接dp下去的。有一个小小的优化操作——单调栈单调递减维护上一行的最大值

上代码——

#include<bits/stdc++.h>//左右走只能从左边出发往右,所以剩下的都是上边的
#define maxn 1005
using namespace std;
int read()
{
    int x = 0, ch = getchar();
    while(!isdigit(ch)) ch = getchar();
    while(isdigit(ch)) x = (x << 1) + (x << 3) + ch - '0', ch = getchar();
    return x;
}
 
int n, m, w[maxn][maxn][2];
int dp[maxn][maxn];
int stc[maxn], top = 0;
int main()
{
//  freopen("in.txt", "r", stdin);
    n = read(), m = read();
    for(int i = 1; i <= n; i++) for(int j = 1; j <= m; j++) w[i][j][0] = w[i][j - 1][0] + read();
    for(int i = 1; i <= n; i++) for(int j = 1; j <= m; j++) w[i][j][1] = w[i][j - 1][1] + read();//每一行前缀和
     
    for(int i = 1; i <= n; i++)
    {
        top = 0;
        for(int j = 0; j <= m; j++)
        {
            while(top && stc[top] < dp[i - 1][j]) top--;//单调栈
            stc[++top] = dp[i - 1][j];//dp是直到当前第i行第j列的最优解
            dp[i][j] = stc[1] + w[i][j][0] + w[i][m][1] - w[i][j][1];
        }
    }
     
    int ans = 0;
    for(int i = 0; i <= m; i++) ans = max(ans, dp[n][i]);
    printf("%d\n", ans);
}

第三题其实dp也很好写,但是由于涉及到高精过于繁琐所以就不整理了QAQ不开高精只能过40的。

hustoj.iso 是一个软件系统镜像文件。Hustoj是一个开源的在线评测系统,它被广泛应用于大学和高中的程序设计教学中。该系统的目标是提供一个方便使用的在线评测和训练环境,使学生能够提交他们的程序代码,并获得即时的评测结果。 hustoj.iso 是Hustoj的系统镜像文件,可以用来部署Hustoj系统。通过将hustoj.iso 文件安装到服务器上,就可以建立一个运行Hustoj系统的评测服务器。用户可以通过web界面访问该服务器,并提交自己的程序代码进行评测。 hustoj.iso 是一个基于Ubuntu操作系统的镜像文件。它集成了所有Hustoj系统所需要的软件和依赖项,并进行了预配置,使得安装和部署变得更加简单。用户只需要将hustoj.iso文件写入到U盘或光盘中,然后引导服务器从U盘或光盘启动,就可以开始安装Hustoj系统了。 使用hustoj.iso 部署Hustoj系统,可以为学生提供一个良好的在线评测环境,帮助他们进行程序设计的学习和训练。学生可以在该系统中提交自己的程序代码,并获得详尽的评测结果,包括运行时间、内存消耗、错误信息等等。同时,Hustoj还具有包括代码分享、竞赛组织等其他功能,能够满足不同需求的学生。 总之,hustoj.iso 是一个用于部署Hustoj系统的镜像文件,通过安装hustoj.iso,可以搭建一个功能完善、易用的在线评测环境,为程序设计学习提供有力的支持。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值