题意:给定一个n首歌的播放列表,第i首的值为a[i],听完第i首会回到第1首

现在从每首开始往下,记录听过的最大值,如果当前听的值严格小于听过最大值的一半则停止

问从每首歌开始往下听能听几首,不会停止则输出-1

n<=1e5,1<=a[i]<=1e9

思路:会D不会C,D的写法还奇渣无比……

因为是环形所以先复制粘贴一遍,然后按a[i]从大到小排个序

对于每个出发点now,设在now之后且离now最近的值比他a[now]的点为nxt,在到达nxt之前其听过的最大值一定为a[now]

如果在now后面的最小值*2>=now后面的最大值则ans[now]=-1

如果now能到达nxt则答案即为ans[nxt]+nxt-now

否则可以二分出第一个不合法的点last,答案即为last-now

对于nxt集合用set维护,对于二分找到第一个不合法的点应该可以在线段树上二分做到一个log,我懒直接外面二分了,两个log

赛场上WA了一发,后面用自己的数据调出来了,今天一看和官方数据一样……我与出题人心意相通

 #include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned int uint;
typedef unsigned long long ull;
typedef pair<int,int> PII;
typedef pair<ll,ll> Pll;
typedef vector<int> VI;
typedef vector<PII> VII;
//typedef pair<ll,ll>P;
#define N 200010
#define M 200010
#define fi first
#define se second
#define MP make_pair
#define pb push_back
#define pi acos(-1)
#define mem(a,b) memset(a,b,sizeof(a))
#define rep(i,a,b) for(int i=(int)a;i<=(int)b;i++)
#define per(i,a,b) for(int i=(int)a;i>=(int)b;i--)
#define lowbit(x) x&(-x)
#define Rand (rand()*(1<<16)+rand())
#define id(x) ((x)<=B?(x):m-n/(x)+1)
#define ls p<<1
#define rs p<<1|1 const ll MOD=1e9+,inv2=(MOD+)/;
double eps=1e-;
int INF=1e9;
int dx[]={-,,,};
int dy[]={,,-,}; int read()
{
int v=,f=;
char c=getchar();
while(c<||<c) {if(c=='-') f=-; c=getchar();}
while(<=c&&c<=) v=(v<<)+v+v+c-,c=getchar();
return v*f;
} set<int>S;
int t[N<<],c[N],ans[N],s[N],b[N]; struct node
{
int x,y;
}a[N]; bool cmp(node a,node b)
{
if(a.x!=b.x) return a.x>b.x;
return a.y<b.y;
}
void pushup(int p)
{
t[p]=min(t[ls],t[rs]);
} void build(int l,int r,int p)
{
if(l==r)
{
t[p]=c[l];
return;
}
int mid=(l+r)>>;
build(l,mid,ls);
build(mid+,r,rs);
pushup(p);
} int query(int l,int r,int x,int y,int p)
{
if(x<=l&&r<=y) return t[p];
int mid=(l+r)>>;
int res=INF;
if(x<=mid) res=min(res,query(l,mid,x,y,ls));
if(y>mid) res=min(res,query(mid+,r,x,y,rs));
return res;
} int main()
{
//freopen("1.in","r",stdin);
int n=read();
int m=n*;
rep(i,,n)
{
a[i].x=read();
a[i].y=i;
}
rep(i,,n) c[i]=a[i].x;
rep(i,n+,m) c[i]=c[i-n];
rep(i,n+,m)
{
a[i].x=a[i-n].x;
a[i].y=i;
}
sort(a+,a+m+,cmp);
build(,m,);
int i=a[].y,mx=a[].x,s=;
while()
{
i++;
if(i==n+) i=;
s++;
if(c[i]*<mx)
{
ans[a[].y]=s;
break;
}
if(s>n)
{
ans[a[].y]=-;
break;
}
}
b[m+]=;
per(i,m,) b[i]=max(b[i+],c[i]);
//printf("s=%d\n",s);
S.clear();
S.insert(a[].y);
int mn=a[].y;
rep(i,,m)
{
//if(a[i].y<=n) int now=a[i].y,res;
if(now>n)
{
ans[now]=ans[now-n];
//mn=min(mn,a[i].y);
S.insert(now);
continue;
}
res=query(,m,now,m,);
if(res*>=b[now])
{
ans[now]=-;
S.insert(now);
continue;
}
set<int>::iterator it=S.upper_bound(now);
//set<int>::iterator it=S.lower_bound(now);
int nxt=(*it);
if(nxt<now&&nxt<=n) nxt+=n;
//printf("i=%d now=%d nxt=%d\n",i,now,nxt);
res=query(,m,now,nxt,);
if(res*>=a[i].x)
{
if(ans[nxt]==-) ans[now]=-;
else ans[now]=ans[nxt]+nxt-now;
}
else
{
int p;
if(a[i].x%==) p=a[i].x/;
else p=a[i].x/+;
int l=now,r=nxt,last=l;
while(l<=r)
{
int mid=(l+r)>>;
int res=query(,m,now,mid,);
if(res<p){last=mid; r=mid-;}
else l=mid+;
}
ans[a[i].y]=last-now;
} S.insert(now);
}
rep(i,,n) printf("%d ",ans[i]);
return ;
}

【CF1237D】Balanced Playlist(set,二分,线段树)的更多相关文章

  1. HDU4614 Vases and Flowers 二分+线段树

    分析:感觉一看就是二分+线段树,没啥好想的,唯一注意,当开始摆花时,注意和最多能放的比大小 #include<iostream> #include<cmath> #includ ...

  2. J - Joseph and Tests Gym - 102020J (二分+线段树)

    题目链接:https://cn.vjudge.net/contest/283920#problem/J 题目大意:首先给你n个门的高度,然后q次询问,每一次询问包括两种操作,第一种操作是将当前的门的高 ...

  3. Educational Codeforces Round 61 D 二分 + 线段树

    https://codeforces.com/contest/1132/problem/D 二分 + 线段树(弃用结构体型线段树) 题意 有n台电脑,只有一个充电器,每台电脑一开始有a[i]电量,每秒 ...

  4. 【BZOJ-3110】K大数查询 整体二分 + 线段树

    3110: [Zjoi2013]K大数查询 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 6265  Solved: 2060[Submit][Sta ...

  5. hdu6070 Dirt Ratio 二分+线段树

    /** 题目:hdu6070 Dirt Ratio 链接:http://acm.hdu.edu.cn/showproblem.php?pid=6070 题意:给定n个数,求1.0*x/y最小是多少.x ...

  6. K-th occurrence HDU - 6704 (后缀数组+二分线段树+主席树)

    大意: 给定串s, q个询问(l,r,k), 求子串s[l,r]的第kk次出现位置. 这是一篇很好的题解: https://blog.csdn.net/sdauguanweihong/article/ ...

  7. POJ - 3264——Balanced Lineup(入门线段树)

    Balanced Lineup Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 68466   Accepted: 31752 ...

  8. HDU5008 Boring String Problem(后缀数组 + 二分 + 线段树)

    题目 Source http://acm.hdu.edu.cn/showproblem.php?pid=5008 Description In this problem, you are given ...

  9. hdu 5649 DZY Loves Sorting 二分+线段树

    题目链接 给一个序列, 两种操作, 一种是将[l, r]里所有数升序排列, 一种是降序排列. 所有操作完了之后, 问你a[k]等于多少. 真心是涨见识了这题..好厉害. 因为最后只询问一个位置, 所以 ...

  10. (困难) CF 484E Sign on Fence,整体二分+线段树

    Bizon the Champion has recently finished painting his wood fence. The fence consists of a sequence o ...

随机推荐

  1. PHP开发一个简单的成绩录入系统

    预览界面 源码: <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> < ...

  2. 关于java范型

    1 范型只在编译阶段有效 编译器在编译阶段检查范型结果之后,就会将范型信息删除.范型信息不会进入运行时阶段. 泛型类型在逻辑上看以看成是多个不同的类型,实际上都是相同的基本类型. 2 不能对确定的范型 ...

  3. The kth great number

    The kth great number Problem Description Xiao Ming and Xiao Bao are playing a simple Numbers game. I ...

  4. PHP 如何实现页面静态化

    页面静态化分为两种 一种伪静态,即url重写,一种纯静态化. 一.静态化的优点: 1有利于搜索引擎收录网站页面的信息:搜索引擎更喜欢静态的,更变于抓取,搜索引擎SEO排名会更容易提高. 2静态网页化网 ...

  5. 通过编写串口助手工具学习MFC过程——(九)自动识别串口的方法

    通过编写串口助手工具学习MFC过程 因为以前也做过几次MFC的编程,每次都是项目完成时,MFC基本操作清楚了,但是过好长时间不再接触MFC的项目,再次做MFC的项目时,又要从头开始熟悉.这次通过做一个 ...

  6. win 10 自带 Ubuntu 系统的文件位置

    win 10 自带 Ubuntu 系统的文件位置 Ubuntu 作为最为流行 Linux 系统中的一种,是用来学习 Linux 相关知识是最好不过的选择.专门搞一个 Ubuntu 系统的电脑不太现实, ...

  7. MVCC/分布式事务简介

    之前我们学习了RocksDB,但这还只是一个最基础的存储引擎.如果想把它在生产环境中用起来,还需要解决很多问题: 如何从单机扩展到分布式? 如何实现事务,并对事务进行并发控制? 用户接口能不能高级一点 ...

  8. Python numpy数据的保存和读取

    在科学计算的过程中,往往需要保存一些数据,也经常需要把保存的这些数据加载到程序中,在 Matlab 中我们可以用 save 和 lood 函数很方便的实现.类似的在 Python 中,我们可以用 nu ...

  9. JavaEE高级-MyBatisPlus学习笔记

    第 1 章 简介 1.1 MyBatisPlus 介绍 -MyBatis-Plus(简称 MP),是一个 MyBatis 的增强工具包,只做增强不做改变. 为简化开发工作.提高生产率而生我们的愿景是成 ...

  10. phonetic

    Simple Classification of English Vowels and Consonants 1.Classifation of English Vowels a)Monophtong ...