题意:

给定一个数组序列,找到一段区间 [ i , j ],使得区间a[i] < a[k] < a[j],( k 是 [ i , j ] 中任意一个数),此处注意 a[i] 是区间唯一最小值,a[j] 是区间唯一最大值。

求 j-i 最大值。(n <= 50000)

思路:

确定左端点,然后找到一个最长区间,使得该区间的最小值为左端点这个值,然后再求出这个区间的最大值,更新答案即可。

所以现在的问题就变成了如何求出最长区间,使得区间最小值为左端点这个值。

最简单的思路就是枚举了,但是时间复杂度上肯定不可行,因此可以考虑进行二分查询,二分右端点,判断这个区间的最小值是否为左端点,即可求出最长的可行区间。

因为不涉及修改,所以如果用 st 表的话,时间复杂度为O(nlogn),如果用线段树的话,时间复杂度为O(n(logn^2)),可能会过不去,需要在二分的时候进行一些优化操作。

总结:

这是一个基础的 线段树+二分 问题,一直T了好久,还是需要加强码力才行。

代码:

#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#define rep(i,a,b) for(int i = a; i <= b; i++)
using namespace std;
const int N = 50000+1000;
const int inf = 0x3fffffff;int n,a[N],lar[N];
struct Tree{int l,r;int minn,maxn;int pos;
}t[4*N];inline int gi()
{int date = 0,m = 1; char ch = 0;while(ch!='-'&&(ch<'0'||ch>'9'))ch = getchar();if(ch=='-'){m = -1; ch = getchar();}while(ch>='0' && ch<='9'){date = date*10+ch-'0';ch = getchar();}return date*m;
}void build(int p,int l,int r)
{t[p].l = l, t[p].r = r;if(l == r){t[p].maxn = t[p].minn = a[l];t[p].pos = l;return;}int mid = (l+r)>>1;build(p*2,l,mid);build(p*2+1,mid+1,r);if(t[p*2].maxn > t[p*2+1].maxn) t[p].maxn = t[p*2].maxn, t[p].pos = t[p*2].pos;else t[p].maxn = t[p*2+1].maxn, t[p].pos = t[p*2+1].pos; t[p].minn = min(t[p*2].minn,t[p*2+1].minn);
}int ask_min(int p,int l,int r)
{if(l <= t[p].l && r >= t[p].r) return t[p].minn;int mid = (t[p].l+t[p].r)>>1;int val = inf;if(l <= mid) val = min(val,ask_min(p*2,l,r));if(r > mid) val = min(val,ask_min(p*2+1,l,r));return val;
}pair<int,int> ask_max(int p,int l,int r)
{if(l <= t[p].l && r >= t[p].r) return make_pair(t[p].maxn,t[p].pos);int mid = (t[p].l+t[p].r)>>1;pair<int,int> tmp(-1,0),tp1;if(l <= mid){tp1 = ask_max(p*2,l,r);if(tmp < tp1) tmp = tp1;else if(tmp == tp1) tmp.second = min(tmp.second,tp1.second);    } if(r > mid){tp1 = ask_max(p*2+1,l,r);if(tmp < tp1) tmp = tp1;else if(tmp == tp1) tmp.second = min(tmp.second,tp1.second); } return tmp;
}int main()
{
//  while(~scanf("%d",&n))while(scanf("%d", &n) != EOF){rep(i,1,n) a[i] = gi();int ans = -1;build(1,1,n);rep(i,1,n){int l = i+1,r = n,cr = -1;while(l <= r){int mid = (l+r)>>1;if((mid-i) <= ans){l = mid+1;continue;}int tmp = ask_min(1,i,mid);//   printf("i:%d,mid:%d,tmp:%d\n",i,mid,tmp);if(tmp < a[i]) r = mid-1;else cr = mid, l = mid+1;}// printf("cr:%d\n",cr);if(cr != -1 && (cr-i) > ans){pair<int,int> tmp = ask_max(1,i,cr);if(tmp.first > a[i])ans = max(ans,tmp.second-i);}}printf("%d\n",ans);}return 0;
}

【POJ-2452】Sticks Problem【二分右端点+线段树】相关推荐

  1. poj 2528 Mayor's posters(线段树+离散化)

    1 /* 2 poj 2528 Mayor's posters 3 线段树 + 离散化 4 5 离散化的理解: 6 给你一系列的正整数, 例如 1, 4 , 100, 1000000000, 如果利用 ...

  2. poj 3468 A Simple Problem with Integers(线段树区区)

    题目链接:  http://poj.org/problem?id=3468 题目大意:  给出N个数,和M次查询 C a b c  区间[a,b]的值都加上c Q a b     查询区间[a,b]值 ...

  3. 【POJ】2828 Buy Tickets(线段树+特殊的技巧/splay)

    http://poj.org/problem?id=2828 一开始敲了个splay,直接模拟. tle了.. 常数太大.. 好吧,说是用线段树.. 而且思想很拽.. (貌似很久以前写过貌似的,,) ...

  4. YbtOJ#463-序列划分【二分答案,线段树,dp】

    正题 题目链接:https://www.ybtoj.com.cn/problem/463 题目大意 给出长度为nnn的序列A,BA,BA,B.要求划分成若干段满足 对于任何i<ji<ji& ...

  5. 【TJOI2016】【bzoj4552】排序(二分答案+线段树01排序)

    problem 给出一个1到n的全排列,现在对这个全排列序列进行m次局部排序 排序分为两种 1:(0,l,r)表示将区间[l,r]的数字升序排序 2:(1,l,r)表示将区间[l,r]的数字降序排序 ...

  6. POJ 2528 Mayor's posters(线段树)

    题目大意 贴海报.每张海报的高度都是一样的,唯独宽度不一样.每张海报只能占用整数倍的单位线段长度,贴了 n(n<=10000) 张海报之后,有几张能够看见(有一个角能看见这张海报也算被看见了)? ...

  7. UOJ#77. A+B Problem [可持久化线段树优化建边 最小割]

    UOJ#77. A+B Problem 题意:自己看 接触过线段树优化建图后思路不难想,细节要处理好 乱建图无果后想到最小割 白色和黑色只能选一个,割掉一个就行了 之前选白色必须额外割掉一个p[i], ...

  8. 猜数(二分、线段树)

    题目描述 对于一个长度为n的数列给出m个描述 每一个描述给出一个区间[a,b]的最小值的x 求从第几个描述开始矛盾 解析 本题关键是一个关于矛盾的充要条件: 如果存在一个最小值x,其所在的区间的交集( ...

  9. CF803G-Periodic RMQ Problem【离散化,线段树,ST表】

    正题 题目链接:https://www.luogu.com.cn/problem/CF803G 题目大意 一个长度为nnn的序列aaa复制kkk份连接,要求支持 区间赋值 区间查询最小值 n,q∈[1 ...

  10. 【BZOJ3958】[WF2011]Mummy Madness 二分+扫描线+线段树

    [BZOJ3958][WF2011]Mummy Madness Description 在2011年ACM-ICPC World Finals上的一次游览中,你碰到了一个埃及古墓. 不幸的是,你打开了 ...

最新文章

  1. Cache 与Memory架构及数据交互
  2. Windows7 32位机上,OpenCV中配置GPU操作步骤
  3. 先进先出置换算法(FIFO)
  4. 开源|如何开发一个高性能的redis cluster proxy?
  5. C语言中能运算符重载吗,C++语言中什么运算符不能重载
  6. Microsoft SQL Server 2005数据库安装
  7. 大学计算机基础方案一,大学计算机基础案例教学与教学案例策划.doc
  8. 五款热门Android手机性能测试 Nexus S大胜
  9. 数据分析工具R和RStudio入门介绍
  10. CTS,CLS,CLR解释
  11. 无法定位程序输入点K32Get Module File Name Ex于动态链接库KERNEL32.dll上 的错误解析
  12. 04Selenium剩余部分及练习:爬取京东商品信息
  13. c语言判断闰年并输出该月天数,C语言宏定义实现闰年判断并输出指定月的天数...
  14. php获取网站备案信息
  15. 更新xcode 12.51时提示空间不足,以及macos的空间清理
  16. linux centos7.x 编译安装php7.4.2
  17. 华为虚拟服务器忘记密码,华为云服务器忘记密码了怎么办
  18. for(i=0,j=0;i10,j10;i++,j++)用python怎么写
  19. Smart License
  20. 使用GrowPart工具完成对LVM逻辑卷的在线热扩容

热门文章

  1. InstallShield 12 制作安装包
  2. [c#基础]关于const和readonly常见的笔试题剖析
  3. 关于SUSE linux
  4. Android--Menus
  5. CHARINDEX 连同 SUBSTRING 对字符串删除处理...
  6. STC学习:八位数码管动态扫描
  7. redis缓存路由为空_千万别看,怕你成为面霸!美团T9总结的Netty+Redis+ZooKeeper核心知识点笔记...
  8. python dry原则_Python 装饰器实现DRY(不重复代码)原则
  9. 1091 Acute Stroke (30 分)广度优先搜索,用queue,重写一遍
  10. uid_t gid_t等的定义