NOIP2017赛前模拟(3):总结
题目:
1.购买板凳(100)
大意:区间修改最后查询全局最大值;
2.新排序(40分暴力)
大意:给一串长度小于100000的数列···每次操作找出序列中严格小于其左边的数字或者严格大于其右边的数字然后删除直到无法操作···最后要求输出最后的序列
3.豆豆游戏(5分dp······)
大意:类似与zuma游戏··给定一个长度小于200的01串··每次往串中插入0或者1构成连续3个相等数字的串的话就能消除····问最少插入多少个0或者1可以消除整个串···注意有连锁反应
题解:
1.差分
略
2.模拟
当然不是纯n方模拟···举个极端例子:50001,50002······100000,1,2,3,4······50000···直接模拟的话就是n方的复杂度··
考虑我们每次删除一对数···每次会影响的只有删除的数列的两端的数···比如上述例子一来我们会删除100000,1,那么受影响的只有99999,2因此我们直接将99999和2加入到另一个队列里面····下次直接考虑新建的队列即可·····
然而考试的时候直接打的n方暴力····其实如果我举出了上述例子还是比较容易想到正解的·····下次题做不出来多举例子试试··
代码:
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<ctime>
#include<cctype>
#include<string>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=1e5+;
const int inf=0x3f3f3f3f;
bool in[N],del[N];
int T,n,a[N],cnt;
struct node
{
int pos,val;
}b[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);
T=R();
while(T--)
{
memset(del,false,sizeof(del));
memset(in,false,sizeof(in));
n=R();bool flag=false;cnt=;
for(int i=;i<=n;i++) a[i]=R();a[]=-inf,a[n+]=inf;
for(int i=;i<=n;i++) if(a[i]>a[i+]||a[i]<a[i-]) del[i]=true,flag=true;
for(int i=;i<=n;i++)
{
if(del[i])
{
if(i>&&!del[i-]&&!in[i-]) b[++cnt]=(node){i-,a[i-]},in[i-]=true;
if(i<n&&!del[i+]&&!in[i+]) b[++cnt]=(node){i+,a[i+]},in[i+]=true;
}
}
while(flag)
{
b[].val=-inf,b[cnt+].val=inf;
flag=false;int temp=;
for(int i=;i<=cnt;i++)
{
in[b[i].pos]=false;
if(b[i].val>b[i+].val||b[i].val<b[i-].val) del[b[i].pos]=true,flag=true;
}
for(int i=;i<=cnt;i++)
{
int p=b[i].pos;
if(del[p])
{
if(p>&&!del[p-]&&!in[p-]) b[++temp]=(node){p-,a[p-]},in[p-]=true;
if(p<n&&!del[p+]&&!in[p+]) b[++temp]=(node){p+,a[p+]},in[p+]=true;
}
else if(!in[p])
b[++temp]=b[i],in[p]=true;
}
cnt=temp;
}
int ans=;
for(int i=;i<=n;i++) if(!del[i]) ans++;
cout<<ans<<endl;
for(int i=;i<=n;i++) if(!del[i]) cout<<a[i]<<" ";
cout<<endl;
}
return ;
}
3.区间dp+分类讨论
md因为4种情况只想到3种直接挂到天上去····
先预处理出每一段的颜色以及数目··考虑f[i][j]表示消除ij段的最小代价···我们可以分成下面4种情况:
第一种:当i==j时:
f[i][i]=3-num[i]
其中num[i]为这i段的数目.
第二种:当col[i]!=col[j]时:
f[i][j]=f[i][k]+f[k+1][j]
其中i<=k<j,col[i]表示i段的颜色 .
第三种:当col[i]=col[j]时:
f[i][j]=min(f[i][j],f[i+1][j-1]+max(0,3-num[i]-num[j]))
第四种:当col[i]=col[j]时:
f[i][j]=min(f[i][j],f[i+1][k-1]+f[k+1][j-1])
其中col[i]=col[j]=col[k]且num[i]+num[j]<4且num[k]=1
代码:
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<ctime>
#include<cctype>
#include<string>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=1e5+;
const int inf=0x3f3f3f3f;
bool in[N],del[N];
int T,n,a[N],cnt;
struct node
{
int pos,val;
}b[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);
T=R();
while(T--)
{
memset(del,false,sizeof(del));
memset(in,false,sizeof(in));
n=R();bool flag=false;cnt=;
for(int i=;i<=n;i++) a[i]=R();a[]=-inf,a[n+]=inf;
for(int i=;i<=n;i++) if(a[i]>a[i+]||a[i]<a[i-]) del[i]=true,flag=true;
for(int i=;i<=n;i++)
{
if(del[i])
{
if(i>&&!del[i-]&&!in[i-]) b[++cnt]=(node){i-,a[i-]},in[i-]=true;
if(i<n&&!del[i+]&&!in[i+]) b[++cnt]=(node){i+,a[i+]},in[i+]=true;
}
}
while(flag)
{
b[].val=-inf,b[cnt+].val=inf;
flag=false;int temp=;
for(int i=;i<=cnt;i++)
{
in[b[i].pos]=false;
if(b[i].val>b[i+].val||b[i].val<b[i-].val) del[b[i].pos]=true,flag=true;
}
for(int i=;i<=cnt;i++)
{
int p=b[i].pos;
if(del[p])
{
if(p>&&!del[p-]&&!in[p-]) b[++temp]=(node){p-,a[p-]},in[p-]=true;
if(p<n&&!del[p+]&&!in[p+]) b[++temp]=(node){p+,a[p+]},in[p+]=true;
}
else
b[++temp]=b[i],in[p]=true;
}
cnt=temp;
}
int ans=;
for(int i=;i<=n;i++) if(!del[i]) ans++;
cout<<ans<<endl;
for(int i=;i<=n;i++) if(!del[i]) cout<<a[i]<<" ";
cout<<endl;
}
return ;
}
NOIP2017赛前模拟(3):总结的更多相关文章
- NOIP2017赛前模拟11月6日—7日总结
收获颇丰的两天··· 题目1:序列操作 给定n个非负整数,进行m次操作,每次操作给出c,要求找出c个正整数数并将它们减去1,问最多能进行多少操作?n,m<=1000000 首先暴力贪心肯定是每次 ...
- NOIP2017赛前模拟11月4日总结:
第一次挂0·····有点感伤···主要是因为时间分配太不合理了··花2个半小时搞第一题最后还wa完了··第二题很简单花了30分钟打完但没打对拍结果wa完···第三题暴力可以拿20分的但没时间打了··· ...
- NOIP2017赛前模拟11月2日总结
分数爆炸的一天··但也学了很多 题目1:活动安排 给定n个活动的开始时间与结束时间··只有一个场地··要求保留尽量多的活动且时间不冲突···场地数n<=100000 考点:贪心 直接将结束时间按 ...
- NOIP2017赛前模拟10月30日总结
题目1: n个人参赛(n<=100000),每个人有一个权值··已知两个人权值绝对值之差小于等于K时,两个人都有可能赢,若大于则权值大的人赢···比赛为淘汰制,进行n-1轮·问最后可能赢的人有多 ...
- NOIP2017赛前模拟(5):总结
题目: 1.刮刮卡 已知n(n<=1000000)张刮刮卡按顺序排列,刮开可以获得B元现金和B个积分,购买刮刮卡需要A元,某人若按照顺序刮开的话··当B的总和小于A时便会停止刮卡(即花出去的钱多 ...
- NOIP2017赛前模拟(4):总结
题目: 1.打牌 给定n个整数(n<=1000000),按照扑克牌对子(x,x)或者顺子(x,x+1,x+2)打出牌···问最多可以打出多少次对子或者顺子?牌的大小<=1000000 2. ...
- NOIP2017赛前模拟1:总结
题目: 1.造盒子 题目描述 企鹅豆豆收到了面积为 K 的一块橡皮泥.但是他没有合适的盒子来装下这个橡皮泥.所以他打算造一个盒子. 制造台是有方形网格的平台,每个小正方形边长为 1 .现在豆豆有两类木 ...
- NOIP2017年11月9日赛前模拟
最后一次NOIP模拟了····· 题目1:回文数字 Tom 最近在研究回文数字. 假设 s[i] 是长度为 i 的回文数个数(不含前导0),则对于给定的正整数 n 有:
- [NOIP2017]时间复杂度(模拟)
sscanf读入数字,getline(cin,string)读一整行,其余暴力模拟即可. #include<cstdio> #include<string> #include& ...
随机推荐
- codeforces Gym 100286H Hell on the Markets
紫书上面的题,队友做的,WA了freopen..爆了int... UVA 1614 - Hell on the Markets 奇怪的股市(贪心,结论)
- Django models多表操作
title: Django models多表操作 tags: Django --- 多表操作 单独创建第三张表的情况 推荐使用的是使用values/value_list,selet_related的方 ...
- Python的ORM介绍
实现方法: SQLOject peewee Django's ORM SQLAlchemy
- python入门:if和else的基本用法
#!/usr/bin/env python # -*- coding:utf-8 -*- #2.X用raw_input,3.X用input #if和else的基本用法 name = input(&qu ...
- PHP 日常开发过程中的bug集合(持续更新中。。。)
PHP 日常开发过程中的bug集合(持续更新中...) 在日常php开发过程中,会遇到一些意想不到的bug,所以想着把这些bug记录下来,以免再犯! 1.字符串 '0.00'.'0.0'.'0' 是 ...
- mysql 编程
一.存储函数 相当于php或者js中有返回值的函数 --完成一定“计算”后返回单个的数据值 定义: create function 函数名(parameter p1 value_type, param ...
- tp5使用外部类的三种方法
在tp5中使用外部类的时候有三种方法 第一种就是通过composer下载,通过这种方式下载的外部类能够支持自动加载,我们只要在使用的时候use一下命名空间就可以使用了 比如:我们的tp5第四季项目要使 ...
- python-for循环与while循环
while 循环 格式: while 条件 为 True: 代码块 while True: rayn_age = 18 age = input('请输入你的年龄:') age = int(age) i ...
- C3P0连接问题
C3P0 连接时的相关问题: 我的环境是在IDEA中使用C3P0中进行的: 使用C3P0主要用到的jar包都是最新和Mysql8.0兼容的包 在连接的时候遇到: 先是在连接的时候出现数据库连接的时候的 ...
- BZOJ 5442: [Ceoi2018]Global warming
[l,r]+x不如[l,n]+x [l,r]-x不如(r,n)+x 所以等价于只有[l,n]+x 枚举断点树状数组合并 难度在于想到这个贪心 #include<cstdio> #inclu ...