[BZOJ3956]Count(单调栈+线段树)
来源:互联网 发布:mac u盘不能拷贝 编辑:程序博客网 时间:2024/05/29 14:43
题目:
我是超链接
题解:
看了看数据范围。。你可能是要求logn出一组解吧。。
好点的配对我们可以用单调栈解决,新来的x都要先和栈顶构成好点啊这个后面就不重复了(以ls为例)
如果新来的 x 大于栈顶元素,弹栈同时ls[i]++,因为可以和前面比自己小的所有数字构成好点,假如前面本来有比x小的但是早就弹出栈了怎么办呢?没事的啊,我们求的是前缀和,会加上前面的部分
如果新来的x 等于栈顶元素,弹栈,因为你会发现有这个相等的家伙拦着,你并不能和前面的点构成好点
如果新来的x 小于栈顶元素,进栈,准备和后面的构成好点
考虑区间[l,r],找出最大高度的下标k
显然l~k-1不能和k之后的元素配对,k+1~r不能和k之前的元素配对,即点对不会跨过最大点
ans=在[l,k]中的配对个数+在[k,r]中的配对个数
这个可以前缀和维护
从前开始扫的时候a[i]表示[1,i]中的配对数量,从后开始扫的时候b[i]表示[i,n]的配对数量
ls[i]=Σa[j] 1<=j<=i
rs[i]=Σb[j] i<=j<=n
毕竟是静态查询最大值,O(n)的RMQ也是资瓷的!
代码:
#include <cstdio>#include <iostream>#include <cstring>#define N 300005using namespace std;int maxx[N*4],a[N],stack[N],ls[N],rs[N];inline void updata(int now){ if (a[maxx[now<<1]]<a[maxx[now<<1|1]]) maxx[now]=maxx[now<<1|1]; else maxx[now]=maxx[now<<1];}void build(int now,int l,int r){ if (l==r){maxx[now]=l;return;} int mid=(l+r)>>1; build(now<<1,l,mid); build(now<<1|1,mid+1,r); updata(now);}int qurry(int now,int l,int r,int lrange,int rrange){ if (lrange<=l && rrange>=r) return maxx[now]; int mid=(l+r)>>1,x=0; if (lrange<=mid) { int lj=qurry(now<<1,l,mid,lrange,rrange); if (a[lj]>=a[x]) x=lj; } if (rrange>mid) { int lj=qurry(now<<1|1,mid+1,r,lrange,rrange); if (a[lj]>a[x]) x=lj; } return x;}int main(){ int n,q,Ty,i; scanf("%d%d%d",&n,&q,&Ty); for (i=1;i<=n;i++) scanf("%d",&a[i]); int top=0; for (int i=1;i<=n;i++) { while (top) { ls[i]++; //每次(除第一次前面无点)必进,因为肯定可以和自己前一个配对 if (a[stack[top]]>=a[i]) break; top--; } while (top){if (a[stack[top]]>a[i]) break;top--;} stack[++top]=i; ls[i]+=ls[i-1]; } top=0; for (int i=n;i>=1;i--) { while (top) { rs[i]++; if (a[stack[top]]>=a[i]) break; top--; } while (top){if (a[stack[top]]>a[i]) break;top--;} stack[++top]=i; rs[i]+=rs[i+1]; } build(1,1,n); int ans=0; while (q--) { int ll,rr; scanf("%d%d",&ll,&rr); int l=min((ll+ans-1)%n+1,(rr+ans-1)%n+1),r=max((ll+ans-1)%n+1,(rr+ans-1)%n+1); if (Ty) ll=l,rr=r; int loc=qurry(1,1,n,ll,rr);//找到l-r中最大值的位置 ans=ls[rr]-ls[loc]+rs[ll]-rs[loc]; printf("%d\n",ans); }}
阅读全文
1 0
- [BZOJ3956]Count(单调栈+线段树)
- [BZOJ3956]Count(单调栈+线段树)
- bzoj3956 -- 单调栈 + 线段树
- 【bzoj3956】【Count】【主席树+单调栈】
- 【BZOJ3956】Count,单调栈+ST表维护区间最大值
- BZOJ3956 Count
- [bzoj3956] Count
- bzoj3956:Count
- [bzoj3956]Count 解题报告
- bzoj3956 Count 解题报告
- HDU 3872 Dragon Ball(DP+线段树+单调栈)
- WOJ 1618 - Magic Array (线段树+单调栈)
- bzoj1012 [JSOI2008]最大数(单调栈+二分/线段树)
- BZOJ4826:[Hnoi2017]影魔 (单调栈+扫描线+线段树)
- bzoj 1012 最大数(线段树|单调队列|单调栈)
- BZOJ 1012 线段树或单调栈
- [BZOJ4826][HNOI2017]影魔-单调栈-线段树
- God Knows 线段树维护单调栈
- Python 旅游博客爬虫
- 关键词final的作用总结
- PHP JavaScript横向总结、对比(1.变量,数据类型)
- flyBanner用法 轮播图效果
- 一个高级PHP工程师所应该具备的能力
- [BZOJ3956]Count(单调栈+线段树)
- Python __init__ 和 self()的一点理解
- Anaconda2和Anaconda3切换Jupyter notebook
- 手把手原生js简单轮播图
- Java并发编程
- org.apache.lucene.queryparser.classic.ParseException: Encountered "<EOF>" at line 1, column 0.
- EPOLL内核源代码实现原理分析
- 深度学习FPGA实现基础知识6(Deep Learning(深度学习)学习资料大全及CSDN大牛博客推荐)
- 剑指offer---二叉树中和为某一值的路径