【洛谷 P1627】 中位数 递推+前缀和思想
2016-11-14 15:24
288 查看
题目描述
给出1~n的一个排列,统计该排列有多少个长度为奇数的连续子序列的中位数是b。中位数是指把所有元素从小到大排列后,位于中间的数。
输入输出格式
输入格式:
第一行为两个正整数n和b,第二行为1~n的排列。
【数据规模】
对于30%的数据中,满足n≤100;
对于60%的数据中,满足n≤1000;
对于100%的数据中,满足n≤100000,1≤b≤n。
输出格式:
输出一个整数,即中位数为b的连续子序列个数。
输入输出样例
输入样例#1:
7 4
5 7 2 4 3 1 6
输出样例#1:
4
题解:一道思路题。我一开始的思路是利用前缀和,维护两个前缀和数组,maxx[i]和minn[i],分别表示1到i这个点之间一共有多少比b大的数和多少比b小的数。那i~j之间比b大的数就可以用maxx[j]−maxx[i−1]得到。最后枚举区间,复杂度是O(n/4)。这样只能过8个点。
正解:记录下b的位置k,第一次循环从k+1到n循环,到该数大于b时,f[i]=f[i−1]+1,反之f[i]=f[i−1]−1,如果f[i]==0则ans++,然后用一个数组p记录p[f[i]]++,表示记录该数出现了多少次。
然后从k-1到1循环,同样用f[i]记录。然后ans+=p[f[i]],f数组含义就是遇到比b大的数就+1,遇到小的数就-1,那么如果b的左右两边出现同一个f[i],那么说明这两个位置之间比b大的数的个数等于比b小的数的个数,那么直接更新答案。复杂度是O(n).
注意,因为c++数组下标不为负数,所以开数组是把所有下标统一加上100000,保证下标为正,同时注意数组大小也要相应增加100000。
http://blog.csdn.net/mitykif orz
给出1~n的一个排列,统计该排列有多少个长度为奇数的连续子序列的中位数是b。中位数是指把所有元素从小到大排列后,位于中间的数。
输入输出格式
输入格式:
第一行为两个正整数n和b,第二行为1~n的排列。
【数据规模】
对于30%的数据中,满足n≤100;
对于60%的数据中,满足n≤1000;
对于100%的数据中,满足n≤100000,1≤b≤n。
输出格式:
输出一个整数,即中位数为b的连续子序列个数。
输入输出样例
输入样例#1:
7 4
5 7 2 4 3 1 6
输出样例#1:
4
题解:一道思路题。我一开始的思路是利用前缀和,维护两个前缀和数组,maxx[i]和minn[i],分别表示1到i这个点之间一共有多少比b大的数和多少比b小的数。那i~j之间比b大的数就可以用maxx[j]−maxx[i−1]得到。最后枚举区间,复杂度是O(n/4)。这样只能过8个点。
正解:记录下b的位置k,第一次循环从k+1到n循环,到该数大于b时,f[i]=f[i−1]+1,反之f[i]=f[i−1]−1,如果f[i]==0则ans++,然后用一个数组p记录p[f[i]]++,表示记录该数出现了多少次。
然后从k-1到1循环,同样用f[i]记录。然后ans+=p[f[i]],f数组含义就是遇到比b大的数就+1,遇到小的数就-1,那么如果b的左右两边出现同一个f[i],那么说明这两个位置之间比b大的数的个数等于比b小的数的个数,那么直接更新答案。复杂度是O(n).
注意,因为c++数组下标不为负数,所以开数组是把所有下标统一加上100000,保证下标为正,同时注意数组大小也要相应增加100000。
http://blog.csdn.net/mitykif orz
#include<cstdio> #include<iostream> #define s 100000 using namespace std; int a[200006],k,ans=0,n; int b,minn[200006],maxx[200006],p[200006],f[200006]; int get() { int x=0,z=1; char c; c=getchar(); if (c==' ') return x*z; while (c<'0'||c>'9') {if (c=='-') z=-1;c=getchar();} while (c>='0'&&c<='9') {x=x*10+c-'0';c=getchar();} return x*z; } void work() { int i; for (i=1;i<=n;i++) { if (a[i]>b) {maxx[i]=maxx[i-1]+1;minn[i]=minn[i-1];} else if (a[i]<b) {minn[i]=minn[i-1]+1;maxx[i]=maxx[i-1];} else if (a[i]==b) {maxx[i]=maxx[i-1];minn[i]=minn[i-1];continue;} } } void love() { int i,j,m1,m2; for (i=1;i<=k;i++) for (j=k;j<=n;j++) if ((j-i)%2==0) { m1=maxx[j]-maxx[i-1]; m2=minn[j]-minn[i-1]; if (m1==m2) { ans++; } } } void distance() { int i,w=0; for (i=k+1;i<=n;i++) { if (a[i]>b) {f[i]=f[i-1]+1;} else {f[i]=f[i-1]-1;} p[f[i]]++; if (f[i]==s) ans++; } for (i=k-1;i>=1;i--) { if (a[i]>b) {f[i]=f[i+1]+1;} else {f[i]=f[i+1]-1;} ans+=p[s+s-f[i]]; if (f[i]==s) ans++; } printf("%d",ans+1); } int main() { int i; n=get();b=get(); for (i=1;i<=n;i++) { a[i]=get(); if (a[i]==b) k=i; } f[k]=s; if (n<=1000) { work(); love(); printf("%d",ans); return 0; } distance(); }
相关文章推荐
- 【洛谷】P1627 中位数
- 极大化思想——洛谷 P1578 奶牛浴场
- 洛谷P1240 诸侯安置 递推
- 快排思想求中位数
- 洛谷P1470 最长前缀
- 【递推】洛谷 P1011 车站
- 【递推】洛谷 P1216 [USACO1.5]数字三角形 Number Triangles
- 题目1157:中位数:快速排序思想
- uva10891 - Game of Sum(递推,极大极小的思想)
- Uva 11300 Spreading the Wealth(递推,中位数)
- 【前缀和思想】cdoj1256昊昊爱运动
- Codeforces Round #271 (Div. 2)D(递推,前缀和)
- 【DP】+【贪心】【前缀和】洛谷P2893 [USACO08FEB]修路Making the Grade 题解
- bzoj 303: [CQOI2009]中位数图【前缀和+瞎搞】
- 【递推】洛谷 P1466 集合 Subset Sums
- 2013-11-04 实验之取球游戏(递推思想,数学归纳思想,思维逻辑思想)
- BSOJ 3022 又一类数字三角形--根据数据范围的优化+背包思想递推/搜索
- [洛谷 2822]组合数问题---二项式定理+前缀和
- 【递推】洛谷 P1095 守望者的逃离
- 【递推】洛谷 P1176 路径计数2