1303: [CQOI2009]中位数图
Time Limit: 1 Sec Memory Limit: 162 MBSubmit: 1256 Solved: 813
[ Submit][ Status]
Description
给出1~n的一个排列,统计该排列有多少个长度为奇数的连续子序列的中位数是b。中位数是指把所有元素从小到大排列后,位于中间的数。
Input
第一行为两个正整数n和b ,第二行为1~n 的排列。
Output
输出一个整数,即中位数为b的连续子序列个数。
Sample Input
7 4
5 7 2 4 3 1 6
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
之前没有想到,然后看到网上的可以把大于b的记为+1,小于b的记为-1,等于的记为0,然后一想就想到了
思考时间
。。。
。。。
。。。
。。。
。。。
。。。
。。。
。。。
。。。
通过上面的记法得到一个0,-1,1的整数序列A
这样就是A中有多少奇数长度连续子序列满足和为0
考虑前缀和S,连续子序列Aj..Ai和为sumij = Si-Sj-1,对于当前位置i有多少j满足sumij==0?
对上式移动一下就可以知道是Si==Sj-1的数量,因为-n<=Si<=n,所以一个标记数组就可以统计了
/**************************************************************
Problem: 1303
User: zhaosdfa
Language: C++
Result: Accepted
Time:80 ms
Memory:3616 kb
****************************************************************/
#include <cstdio>
#include <iostream>
#include <vector>
#include <algorithm>
#include <cstring>
#include <string>
#include <map>
#include <cmath>
#include <queue>
#include <set>
using namespace std;
//#define WIN
#ifdef WIN
typedef __int64 LL;
#define iform "%I64d"
#define oform "%I64d\n"
#define oform1 "%I64d"
#else
typedef long long LL;
#define iform "%lld"
#define oform "%lld\n"
#define oform1 "%lld"
#endif
#define S64I(a) scanf(iform, &(a))
#define P64I(a) printf(oform, (a))
#define P64I1(a) printf(oform1, (a))
#define REP(i, n) for(int (i)=0; (i)<n; (i)++)
#define REP1(i, n) for(int (i)=1; (i)<=(n); (i)++)
#define FOR(i, s, t) for(int (i)=(s); (i)<=(t); (i)++)
const int INF = 0x3f3f3f3f;
const double eps = 1e-9;
const double PI = (4.0*atan(1.0));
const int maxn = 100000 + 20;
int A[maxn];
int sum[maxn];
int vis[maxn*2];
int vis1[maxn*2];
int main() {
int n, b, ans = 0;
scanf("%d%d", &n, &b);
int G = n;
sum[0] = 0;
memset(vis, 0, sizeof(vis));
memset(vis1, 0, sizeof(vis1));
for(int i=1; i<=n; i++) {
int t;
scanf("%d", &t);
if(t > b) A[i] = 1;
else if(t == b) A[i] = 0;
else A[i] = -1;
sum[i] = sum[i-1] + A[i];
int tn = sum[i];
if(tn == 0 && (i&1)) ans++;
if(i&1) ans += vis1[tn + G];
else ans += vis[tn + G];
if(i&1) vis[sum[i] + G]++;
else vis1[sum[i] + G]++;
}
printf("%d\n", ans);
return 0;
}