BZOJ3152[Ctsc2013]组合子逻辑——堆+贪心
2024-09-26 15:14:12
题目链接:
题目大意:
一开始有一个括号包含[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);
}
}
最新文章
- SharePoint 2013 文档库中PPT转换PDF
- Android开发常用工具类
- Linux通过NAT方式配置网络
- Use Dapper ORM With ASP.NET Core
- ecshop /includes/init.php Arbitrary User Login Vul
- 20145330第五周《Java学习笔记》
- iOS - C 应用
- C#与数据库访问技术总结(十八)
- mysql 线程池 数据库连接池
- whu 1464 deal with numbers
- GitHub详细教程
- mrql初级教程-使用(er)
- vue $refs 无法动态拼接,获取不到对象(转)
- POI 生成excel(大数据量) SXSSF
- Python爬虫【三】利用requests和正则抓取猫眼电影网上排名前100的电影
- 《剑指offer》第五十九题(滑动窗口的最大值)
- P499 usebrass2
- 转:双向链表dblinklist
- 【转】Java学习---内存溢出的排查经历
- 安装Tidb数据库出现SSD硬盘IOPS不到40000的错误