[BZOJ1303] [CQOI2009] 中位数图

Description

  给出1~n的一个排列,统计该排列有多少个长度为奇数的连续子序列的中位数是b。中位数是指把所有元素从小到大排列后,位于中间的数。

Input

  第一行为两个正整数n和b ,第二行为1~n 的排列。

Output

  输出一个整数,即中位数为b的连续子序列个数。

Sample Input

7 4
5 7 2 4 3 1 6

Sample Output

4

HINT

  第三个样例解释:{4}, {7,2,4}, {5,7,2,4,3}和{5,7,2,4,3,1,6}
  N<=100000

Source

Solution

  本题总时限1s,那么一个测试点0.1s,需要一个O(n)的算法,好像排序都不能用。

  我们换一种思路:

  设a[cur] = b, [l, r]表示满足题意的一个区间。

  因为b一定在序列中,所以l < cur,r > cur,因为b是中位数,所以比b大的数的个数=比b小的数的个数。

  令c[n] = a[n]~a[cur]中,大于b的数的个数减小于b的数的个数,或c[n] = a[cur]~a[n]中,小于b的数的个数减大于b的数的个数。

  所以若[l, r]满足条件,必有c[l] == c[r]。

  统计答案时用桶排序维护答案即可保证复杂度。

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 int a[100005], c[100005], sum[200005];
 4 int main()
 5 {
 6     int n, b, cur, ans = 0;
 7     cin >> n >> b;
 8     for(int i = 1; i <= n; i++)
 9     {
10         cin >> a[i];
11         if(b == a[i]) cur = i;
12     }
13     for(int i = cur; i; i--)
14     {
15         sum[c[i] + n]++;
16         c[i - 1] = c[i] + (a[i - 1] > b ? 1 : -1);
17     }
18     for(int i = cur; i <= n; i++)
19     {
20         ans += sum[c[i] + n];
21         c[i + 1] = c[i] + (a[i + 1] > b ? -1 : 1);
22     }
23     cout << ans << endl;
24     return 0;
25 }

时间: 2024-08-25 16:53:34

[BZOJ1303] [CQOI2009] 中位数图的相关文章

bzoj千题计划175:bzoj1303: [CQOI2009]中位数图

http://www.lydsy.com/JudgeOnline/problem.php?id=1303 令c[i]表示前i个数中,比d大的数与比d小的数的差,那么如果c[l]=c[r],则[l+1,r]满足条件 #include<cstdio> #include<iostream> using namespace std; const int N=1e7; int c[N*2],g[N]; void read(int &x) { x=0; char c=getchar()

bzoj 1303: [CQOI2009]中位数图 数学

1303: [CQOI2009]中位数图 Time Limit: 20 Sec  Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnline/problem.php?id=1303 Description 给出1~n的一个排列,统计该排列有多少个长度为奇数的连续子序列的中位数是b.中位数是指把所有元素从小到大排列后,位于中间的数. Input 第一行为两个正整数n和b ,第二行为1~n 的排列. Output 输出一个整数,即中位数为b的

BZOJ 1303: [CQOI2009]中位数图【前缀和】

1303: [CQOI2009]中位数图 Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 2737  Solved: 1698[Submit][Status][Discuss] Description 给出1~n的一个排列,统计该排列有多少个长度为奇数的连续子序列的中位数是b.中位数是指把所有元素从小到大排列后,位于中间的数. Input 第一行为两个正整数n和b ,第二行为1~n 的排列. Output 输出一个整数,即中位数为b的连续子序列个数.

【BZOJ 1303】 [CQOI2009]中位数图

1303: [CQOI2009]中位数图 Time Limit: 1 Sec  Memory Limit: 162 MB Submit: 1452  Solved: 951 [Submit][Status] Description 给出1~n的一个排列,统计该排列有多少个长度为奇数的连续子序列的中位数是b.中位数是指把所有元素从小到大排列后,位于中间的数. Input 第一行为两个正整数n和b ,第二行为1~n 的排列. Output 输出一个整数,即中位数为b的连续子序列个数. Sample

1303: [CQOI2009]中位数图

1303: [CQOI2009]中位数图 Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 1383  Solved: 902[Submit][Status] Description 给出1~n的一个排列,统计该排列有多少个长度为奇数的连续子序列的中位数是b.中位数是指把所有元素从小到大排列后,位于中间的数. Input 第一行为两个正整数n和b ,第二行为1~n 的排列. Output 输出一个整数,即中位数为b的连续子序列个数. Sample In

【bzoj1303】[CQOI2009]中位数图

一个大于b的数和一个小于b的数可以互相抵消,所以我们用1和-1表示. 从b向两边扩展,left[i]表示b左边抵消后有i个数比b小的可能数,right[i]表示b右边抵消后有i个数比b大的可能数. ans=sigma(left[i]*right[i]). #include<algorithm> #include<iostream> #include<cstdlib> #include<cstring> #include<cstdio> #incl

bzoj 1303: [CQOI2009]中位数图

1 #include<cstdio> 2 #include<iostream> 3 #define M 100005 4 using namespace std; 5 int a[M],l[2*M],r[2*M],sum[M],n,m,p,ans; 6 int main() 7 { 8 scanf("%d%d",&n,&m); 9 for(int i=1;i<=n;i++) 10 { 11 scanf("%d",&

BZOJ 1303: [CQOI2009]中位数图 【水题】

给出1~n的一个排列,统计该排列有多少个长度为奇数的连续子序列的中位数是b.中位数是指把所有元素从小到大排列后,位于中间的数. Input 第一行为两个正整数n和b ,第二行为1~n 的排列. Output 输出一个整数,即中位数为b的连续子序列个数. Sample Input 7 45 7 2 4 3 1 6 Sample Output 4 HINT 第三个样例解释:{4}, {7,2,4}, {5,7,2,4,3}和{5,7,2,4,3,1,6}N<=100000 思路:记录中间那个数左边右

bzoj[CQOI2009]中位数图

又是一道巧妙的题 将大于b的数标为1,将小于b的数标为-1 以b为界限,向两边分别求后缀和与前缀和,用l,r分别统计左右两边每个前缀和的数量 因为前缀和有负数所以整体加个n 于是答案就是l[i]*r[2*n-i]//和为2*n,即减去加上的n,和为0,此时b为中位数 因为题目中说要满足长度为奇数,此时若两个和加起来为2*n,个数相加一定为偶数,加上一个b就为奇数了 #include<bits/stdc++.h> using namespace std; const int maxn=10000