题目:

1.造盒子

题目描述

企鹅豆豆收到了面积为 K 的一块橡皮泥。但是他没有合适的盒子来装下这个橡皮泥。所以他打算造一个盒子。

制造台是有方形网格的平台,每个小正方形边长为 1 。现在豆豆有两类木板,一类只能放在小正方形的边上,一类只能放在小正方形的对角线上。

现在豆豆想知道最少需要用多少块木板来制造一个封闭的盒子来把橡皮泥放下去。

输入格式

第一行一个整数 T 表示数据组数。
对于每组数据的第一行一个整数 K ,表示橡皮泥的大小。

输出格式

输出一个整数表示最少需要的木板数目

样例数据 1

输入  [复制]






5

输出





7

备注

【数据范围】
对于 50% 的数据,K≤20。
对于 100% 的数据,K≤109。

2.分玩具

题目描述

豆豆和豆沙正在分一些玩具,每个玩具有一个好玩值,每个人可以拿走任意数量的玩具,获得的愉快度为最小的好玩值。现在豆豆先拿,每个人轮流操作,直到没有玩具可以拿。豆豆想知道他能比豆沙多出多少愉快度?

输入格式

第一行 N 表示玩具个数。
接下来一行 N 个整数表示第 i 个玩具的好玩值。

输出格式

输出一个整数表示最多多出的愉快度。

样例数据 1

输入  [复制]


1 3 1

输出

2

备注

【数据范围】
对于 30% 的数据,N≤10。
对于 70% 的数据,N≤1000。
对于 100 %的数据,N≤1000000,0≤数值范围≤109。

3.problem

题目描述

今天豆豆在做作业的时候遇到这么一个问题:

给出 N 个正整数 a1..aN ,再给出一个正整数 k ,现在可以进行如下操作:每次选择一个大于 k 的正整数 ai,将 ai 减去 1 ,选择 a[i-1] 或 a[i+1] 中的一个加上 1 。经过一定次数的操作后,最大能够选出多长的一个连续子序列,使得这个子序列的每个数都不小于 k 。

总共有 M 次询问,每次询问给出的一个 k ,回答这个询问。

输入格式

第一行两个整数 N , m 代表数组长度和询问个数。
接下来一行,第 i 个正整数表示 ai 。
第三行 M 个正整数,第 i 个正整数表示第 i 次询问的 k 。

输出格式

对于每个询问,输出一个整数表示问题的答案。

样例数据 1

输入  [复制]

5 6 
1 2 1 1 5 
1 2 3 4 5 6

输出

5 5 2 1 1 0

备注

对于 20% 的数据,N≤10。
对于 40% 的数据,N≤1000。
对于 50% 的数据,N≤100000。 
对于 100% 的数据,N≤1000000,M≤20,ai≤109,k≤109。
请选手注意自己的常数。

题解:

1.找规律

首先找到最‘划算’的填补方式·····当面积等于k*k*2时··无疑是斜着的正方形最优··然后沿着四条边一次填补·····于是规律就可以找到了··

代码:

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<ctime>
#include<cctype>
#include<cstring>
#include<string>
#include<algorithm>
using namespace std;
int a,t;
int ans[]={,,,,,,,,,,,,,,,,,,,,};
inline int R()
{
char c;int f=;
for(c=getchar();c<''||c>'';c=getchar());
for(;c<=''&&c>='';c=getchar()) f=(f<<)+(f<<)+c-'';
return f;
}
int main()
{
t=R();
while(t--)
{
a=R();
if(a<=)
cout<<ans[a]<<endl;
else
{
int k=(int)sqrt(a/);
if(k*k*==a) cout<<k*<<endl;
else if(a>k*k*&&a<=(*k*k+(k-))) cout<<k*+<<endl;
else if(a>(*k*k+k-)&&a<=(*k*k+*k)) cout<<k*+<<endl;
else if(a>(*k*k+*k)&&a<=(*k*k+*k)) cout<<k*+<<endl;
else if(a>(*k*k+*k)&&a<=(*k*k+*k+)) cout<<k*+<<endl;
}
}
return ;
}

2.dp

先将玩具从大到小排序然后离散化·····用dp[i]表示先手选择i-n范围内的玩具时最多多出的好玩度·····得出dp方程:

dp[i]=max(maxx,num[i]-dp[i-1])

其中maxx是max(dp[i-1——n])(因为两个人都很聪明··肯定会选最大值····)

md这个dp方程太巧妙了···

代码:

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<ctime>
#include<cctype>
#include<cstring>
#include<string>
#include<algorithm>
using namespace std;
const int N=1e6+;
int ans,maxx,n,dp[N],num[N];
inline int R()
{
char c;int f=;
for(c=getchar();c<''||c>'';c=getchar());
for(;c<=''&&c>='';c=getchar())
f=(f<<)+(f<<)+c-'';
return f;
}
bool cmp(int a,int b)
{
return a>b;
}
int main()
{
n=R();
for(int i=;i<=n;i++) num[i]=R();
sort(num+,num+n+,cmp);
n=unique(num+,num+n+)-num-;
dp[n]=num[n];
for(int i=n;i>=;i--)
dp[i]=maxx=max(maxx,num[i]-dp[i+]);
cout<<dp[]<<endl;
return ;
}

3.单调栈

这道题就是找最长的一段平均值大于k的长度·····

为了消除k的影响,我们将每个数减去k··这样就是找最长的一段平均值大于0的长度····

然后计算前缀和···我们对于sum[i],我们要找到sum[1-i-1]中小于sum[i]且最靠近左边的j用i-j更新答案···

因此我们一边从1到n枚举i,一边维护一个sum递减的单调队栈···

然后记录一个指针tail,如果sum[i]>sum[tail],就一直将指针向左移动找到边界更新答案··反之就往左移···

这样由于每次往右移动最多一次(保证答案最优)···而往左移动的次数是小于等于往右移动的次数的···所以每次询问的复杂度为O(n)·······

代码:

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<ctime>
#include<cctype>
#include<cstring>
#include<string>
#include<algorithm>
using namespace std;
const int N=1e6+;
long long num[N],sum[N];
int n,m,k,tot,tail,ans,stack[N];
inline int R()
{
char c;int f=;
for(c=getchar();c<''||c>'';c=getchar());
for(;c<=''&&c>='';c=getchar()) f=(f<<)+(f<<)+c-'';
return f;
}
int main()
{
//freopen("a.in","r",stdin);
n=R();m=R();
for(int i=;i<=n;i++) num[i]=R(),num[i]+=num[i-];
while(m--)
{
k=R();ans=;tot=;
for(int i=;i<=n;i++) sum[i]=num[i]-(long long)k*i;
for(int i=;i<=n;i++)
{
if(sum[i]>=) ans=max(ans,i);
if(!tot) stack[++tot]=i,tail=tot;
else if(sum[i]<sum[stack[tot]])
{
stack[++tot]=i,tail=tot;
if(sum[i]-sum[i-]>=) ans=max(ans,);
}
else
{
if(sum[stack[tail]]>sum[i])
{
if(tail+<=tot) tail++;
if(sum[stack[tail]]<=sum[i]) ans=max(ans,i-stack[tail]);
}
else
{
ans=max(ans,i-stack[tail]);
while(sum[stack[tail-]]<=sum[i]&&tail->)
tail--;
ans=max(ans,i-stack[tail]);
}
}
}
cout<<ans<<" ";
}
return ;
}

NOIP2017赛前模拟1:总结的更多相关文章

  1. NOIP2017赛前模拟(3):总结

    题目: 1.购买板凳(100) 大意:区间修改最后查询全局最大值; 2.新排序(40分暴力) 大意:给一串长度小于100000的数列···每次操作找出序列中严格小于其左边的数字或者严格大于其右边的数字 ...

  2. NOIP2017赛前模拟11月6日—7日总结

    收获颇丰的两天··· 题目1:序列操作 给定n个非负整数,进行m次操作,每次操作给出c,要求找出c个正整数数并将它们减去1,问最多能进行多少操作?n,m<=1000000 首先暴力贪心肯定是每次 ...

  3. NOIP2017赛前模拟11月4日总结:

    第一次挂0·····有点感伤···主要是因为时间分配太不合理了··花2个半小时搞第一题最后还wa完了··第二题很简单花了30分钟打完但没打对拍结果wa完···第三题暴力可以拿20分的但没时间打了··· ...

  4. NOIP2017赛前模拟11月2日总结

    分数爆炸的一天··但也学了很多 题目1:活动安排 给定n个活动的开始时间与结束时间··只有一个场地··要求保留尽量多的活动且时间不冲突···场地数n<=100000 考点:贪心 直接将结束时间按 ...

  5. NOIP2017赛前模拟10月30日总结

    题目1: n个人参赛(n<=100000),每个人有一个权值··已知两个人权值绝对值之差小于等于K时,两个人都有可能赢,若大于则权值大的人赢···比赛为淘汰制,进行n-1轮·问最后可能赢的人有多 ...

  6. NOIP2017赛前模拟(5):总结

    题目: 1.刮刮卡 已知n(n<=1000000)张刮刮卡按顺序排列,刮开可以获得B元现金和B个积分,购买刮刮卡需要A元,某人若按照顺序刮开的话··当B的总和小于A时便会停止刮卡(即花出去的钱多 ...

  7. NOIP2017赛前模拟(4):总结

    题目: 1.打牌 给定n个整数(n<=1000000),按照扑克牌对子(x,x)或者顺子(x,x+1,x+2)打出牌···问最多可以打出多少次对子或者顺子?牌的大小<=1000000 2. ...

  8. NOIP2017年11月9日赛前模拟

    最后一次NOIP模拟了····· 题目1:回文数字 Tom 最近在研究回文数字. 假设 s[i] 是长度为 i 的回文数个数(不含前导0),则对于给定的正整数 n 有:

  9. [NOIP2017]时间复杂度(模拟)

    sscanf读入数字,getline(cin,string)读一整行,其余暴力模拟即可. #include<cstdio> #include<string> #include& ...

随机推荐

  1. 【转】JavaScript 节点操作 以及DOMDocument属性和方法

    最近发现DOMDocument对象很重要,还有XMLHTTP也很重要 注意大小写一定不能弄错. 属性: 1Attributes 存储节点的属性列表(只读) 2childNodes 存储节点的子节点列表 ...

  2. java的IO机制

    BIO.NIO.AIO -----> Block-IO : inputStream 和OutputStream,Reader和Writer 1个连接,启动一个线程,这样导致很大的线程开销 NIO ...

  3. 01_3Java Application初步

    01_3Java Application初步 l Java源文件以“java”为扩展名.源文件的基本组成部分是类(class),如本例中的HelloWorld类. l 一个源文件中最多只有一个publ ...

  4. CocoaPods在OS X Yosemite上突然不能用了的解决办法

    最近开发的时候发现自己的CocoaPods不能使用了! 根据报的错误上网搜寻answer,于是搜到了解决办法 在 OS X Yosemite 报这样的错: [MT] DVTAssertions: AS ...

  5. iOS跳转到各种系统设置界面

    定位服务 定位服务有很多APP都有,如果用户关闭了定位,那么,我们在APP里面可以提示用户打开定位服务.点击到设置界面设置,直接跳到定位服务设置界面.代码如下: //定位服务设置界面 NSURL *u ...

  6. 【树形dp】bzoj4726: [POI2017]Sabota?

    找点概率期望的题做一做 Description 某个公司有n个人, 上下级关系构成了一个有根树.其中有个人是叛徒(这个人不知道是谁).对于一个人, 如果他 下属(直接或者间接, 不包括他自己)中叛徒占 ...

  7. pandas交叉表和透视表及案例分析

    一.交叉表: 作用: 交叉表是一种用于计算分组频率的特殊透视图,对数据进行汇总 考察预测数据和正式数据的对比情况,一个作为行,一个作为列 案例: 医院预测病人病情: 真实病情如下数组(B:有病,M:没 ...

  8. C#_接口基础学习

    参考:https://www.cnblogs.com/hamburger/p/4681681.html

  9. iPhone如何设置自定义铃声?无需连接电脑,轻松几步就搞定!

    转载自: https://baijiahao.baidu.com/s?id=1594988016778457969&wfr=spider&for=pc 受够了iPhone自带的千篇一律 ...

  10. 《linux设备驱动开发详解》笔记——18 ARM linux设备树

    18.1 设备树的起源 linux 2.6及之前,大量板级信息被硬编码到内核里,十分庞大,大量冗余代码: linux 2.6之前,引入了设备树: 设备树源于OpenFirmware,描述硬件的数据结构 ...