Tyvj4875:排列 (单调栈)
2017-09-27 16:49
232 查看
题目传送门:http://tyvj.cn/p/4875
题目分析:真是一道神题,我考试的时候想了1h都没想出来,最后只好码了个暴力,没想到正解和暴力之间就差一个小优化……
朴素的O(n2)暴力是固定左端点,然后R指针往右扫更新Min和Max值,令ans[Max-Min]加1,最后对ans数组做个前缀和。然而由于a数组是随机生成的,所以Max和Min的取值只会有log(n)个(题解上是这么说的,但我并不会具体的证明),于是我们只需要关注令Max和Min变化的R值就好了。那我们怎么知道Max和Min在什么时候变化呢?以Max为例,我们令L从右往左扫,并一边用一个元素值单调下降的栈维护Max变化的位置。这样L指针左移的时候,就相当于多了一个数字,将其加入栈顶,弹出前面比它小的元素,最后栈中的元素即为变化的Max值。
CODE:
题目分析:真是一道神题,我考试的时候想了1h都没想出来,最后只好码了个暴力,没想到正解和暴力之间就差一个小优化……
朴素的O(n2)暴力是固定左端点,然后R指针往右扫更新Min和Max值,令ans[Max-Min]加1,最后对ans数组做个前缀和。然而由于a数组是随机生成的,所以Max和Min的取值只会有log(n)个(题解上是这么说的,但我并不会具体的证明),于是我们只需要关注令Max和Min变化的R值就好了。那我们怎么知道Max和Min在什么时候变化呢?以Max为例,我们令L从右往左扫,并一边用一个元素值单调下降的栈维护Max变化的位置。这样L指针左移的时候,就相当于多了一个数字,将其加入栈顶,弹出前面比它小的元素,最后栈中的元素即为变化的Max值。
CODE:
#include<iostream> #include<string> #include<cstring> #include<cmath> #include<cstdio> #include<cstdlib> #include<stdio.h> #include<algorithm> using namespace std; const int maxn=100100; typedef long long LL; LL sum[maxn]; int small[maxn]; int big[maxn]; int scur,bcur; int a[maxn]; int t,n; void Push(int x) { small[++scur]=x; while ( scur>1 && a[ small[scur-1] ]>a[ small[scur] ] ) scur--,small[scur]=small[scur+1]; big[++bcur]=x; ec19 while ( bcur>1 && a[ big[bcur-1] ]<a[ big[bcur] ] ) bcur--,big[bcur]=big[bcur+1]; } int main() { freopen("sum.in","r",stdin); freopen("sum.out","w",stdout); scanf("%d",&t); while (t--) { scur=bcur=0; memset(sum,0,sizeof(sum)); scanf("%d",&n); for (int i=1; i<=n; i++) scanf("%d",&a[i]); sum[0]=n; small[++scur]=n; big[++bcur]=n; for (int L=n-1; L>=1; L--) { Push(L); int last=n+1,x=1,y=1; while (small[x]!=big[y]) { int now=max(small[x],big[y]); sum[ a[ big[y] ]-a[ small[x] ] ]+=(last-now); last=now; if (big[y]>small[x]) y++; else x++; } } for (int i=1; i<n; i++) sum[i]+=sum[i-1]; for (int i=0; i<n; i++) printf("%lld\n",sum[i]); } return 0; }
相关文章推荐
- tyvj4875 排列(单调栈)
- tyvj4875:排列(单调栈)
- BZOJ_P3100 排列(单调栈)
- [Tyvj P4875]排列
- [Tyvj1939] 玉蟾宫(单调栈)
- [Tyvj P4876]近似排列计数[50]
- LuoguP1439 排列求最长公共子序列【DP+单调栈】
- Lintcode:整数排列
- tyvj 1040 表达式计算
- 输入若干个自然数,对奇数从大到小排列,对偶数从小到大排列,输出两种结果。
- 由大到小排列a,b,c
- hdu1716排列2
- hdu 5020 排列组合+stl map (或者离散化)
- Morse Code HNUST 1675(字符串全排列 递归解决 数组a[]与流输入的缓慢)
- tyvj P1000:A+B problem
- Tyvj专题 数字三角形
- UVA11077 Find the Permutations(排列统计)
- Vertical Text with CSS(用CSS竖向排列文本)
- leetcode:Permutations排列
- Tyvj1953:Normal (点分治+FFT)