题目链接:

BZOJ3152

题目大意:

一开始有一个括号包含[1,n],你需要加一些括号,使得每个括号(包括一开始的)所包含的元素个数要<=这个括号左端点那个数的大小,当一个括号包含另一个括号时,里面那个括号内所有数整体被看作是一个元素。

假设一个括号包含[L,R],它之中有一个括号包含[l,r],那么这段区间长度最长为L+l-1,也就可以看做这段区间前L个被L括起来,后l-1个被l括起来。

那么题目也就可以转化成选择一个数num可以覆盖以他为左端点的往后num个数,询问最少选几个数能覆盖整个数列。

刚开始第一个数一定要选的,那么先往后覆盖a1个数,要想再往后覆盖就要在这前a1个数中再找一个数来继续覆盖下去。

因为要使得所选的数尽量少,所以要选前面中ai最大的。

那么我们用堆维护这个东西,每当一个数ai被覆盖时将它压入堆中,当当前选的数覆盖不了时再在堆顶选取最大的那个继续覆盖下去。

注意ai=1的特判。

#include<set>
#include<map>
#include<queue>
#include<stack>
#include<cmath>
#include<cstdio>
#include<vector>
#include<bitset>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
priority_queue<int>q;
int T;
int n;
int a[2000010];
int now;
int ans;
int flag;
int main()
{
scanf("%d",&T);
while(T--)
{
while(!q.empty())
{
q.pop();
}
ans=0;
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
}
if(n==1)
{
printf("0\n");
continue;
}
now=a[1]-1;
ans++;
flag=0;
if(now==0)
{
printf("-1\n");
continue;
}
for(int i=2;i<=n;i++)
{
if(now==0)
{
now=q.top()-1;
q.pop();
if(now==0)
{
flag=1;
break;
}
ans++;
}
now--;
q.push(a[i]);
}
if(flag==1)
{
printf("-1\n");
continue;
}
printf("%d\n",ans);
}
}

最新文章

  1. SharePoint 2013 文档库中PPT转换PDF
  2. Android开发常用工具类
  3. Linux通过NAT方式配置网络
  4. Use Dapper ORM With ASP.NET Core
  5. ecshop /includes/init.php Arbitrary User Login Vul
  6. 20145330第五周《Java学习笔记》
  7. iOS - C 应用
  8. C#与数据库访问技术总结(十八)
  9. mysql 线程池 数据库连接池
  10. whu 1464 deal with numbers
  11. GitHub详细教程
  12. mrql初级教程-使用(er)
  13. vue $refs 无法动态拼接,获取不到对象(转)
  14. POI 生成excel(大数据量) SXSSF
  15. Python爬虫【三】利用requests和正则抓取猫眼电影网上排名前100的电影
  16. 《剑指offer》第五十九题(滑动窗口的最大值)
  17. P499 usebrass2
  18. 转:双向链表dblinklist
  19. 【转】Java学习---内存溢出的排查经历
  20. 安装Tidb数据库出现SSD硬盘IOPS不到40000的错误

热门文章

  1. Android Studio在华为真机上运行无法输出Debug日志解决
  2. C语言程序设计II—第四周教学
  3. Redis 安装部署
  4. three.js - 添加材质 灯光 阴影
  5. GPXReader工具代码简析
  6. 利用数据库触发器让字段与自增长Id相关联
  7. MVC4程序运行报错
  8. 浅谈博弈论中的两个基本模型——Bash Game&amp;&amp;Nim Game
  9. [Socket]Socket文件传输
  10. 做完小程序项目、老板给我加了5k薪资~