[CQOI2009]中位数图 (思维)
思路:
感觉这个题很偏向思维,原谅本蒟蒻看了题解后才想明白。
首先要考虑到的就是题目中的大小关系都只是一个相对的关系,所以大于b的数对答案的贡献都是一样的,小于b的数对答案的贡献都是一样的。不妨就设大于b的数的值为1,小于b的数的值为-1,等于b的数的值为0。
所以问题就转化成了求一个区间和为0的而且内部元素有0的长度为奇数的区间个数。
因为1和-1要相互抵消,而区间内又必须含有0,所以区间的长度就一定是奇数。
所以可以以0为起点,分别统计前后缀,前缀和为x时,后缀和一定为-x才能符合题意。所以分别用l,r两个数组表示和为x的数的个数,最后遍历一遍求出结果即可。
因为数组的下标不可以为负数,所以要同时平移,当所有的数都是-1时,和为-n,所以平移n个单位即可。
代码:
#include<bits/stdc++.h> using namespace std; const int maxn=110000; int a[maxn],l[maxn],r[maxn],sum[maxn]; int main(){ int n,b; cin>>n>>b; int pos; for(int i=1;i<=n;i++){ cin>>a[i]; if(a[i]>b) a[i]=1; else if(a[i]<b) a[i]=-1; else a[i]=0,pos=i; } l[n]=r[n]=1; for(int i=pos+1;i<=n;i++) sum[i]=sum[i-1]+a[i],r[sum[i]+n]++; for(int i=pos-1;i>=1;i--) sum[i]=sum[i+1]+a[i],l[sum[i]+n]++; int res=0; for(int i=0;i<2*n;i++) res+=(l[i]*r[2*n-i]); cout<<res<<endl; return 0; }