牛客 [CQOI2009]中位数图
作者:互联网
题目链接:https://ac.nowcoder.com/acm/problem/19913
因为是中位数的位置,所以可以不考虑其他数字是什么,只需要知道相对大小即可
那么让大于b的数变为1 小于b的数变为-1 等于b的数变为0
第一反应是求了前缀和 然后却只能n^2 求每个区间来判断是否满足条件 显然会T
正解应该是以 0为中心 对0的左边求一次后缀和 对0的右边求一次前缀和 这样是为了确保是一段连续的子序列
然后 先记录右边的前缀和 为i 的有多少个 再去遍历左边的后缀和 当左边后缀和为i时 找刚刚记录的前缀和有多少个-i ,-i就是贡献度
而如果是0的话 本身也可以++ 0的话除了只有b本身之外 一定是偶数个 那么+上b就是奇数个
同理 两边 的前缀和和后缀和 相加也一定是偶数个 那么加上b本身也是奇数个 所以奇数的问题就不用考虑了
时间复杂度 o(n)
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define ll long long 4 #define pb push_back 5 const int maxn =2e5+10; 6 const int mod=1e9+7; 7 int a[maxn]; 8 int main() 9 { 10 ios::sync_with_stdio(false); 11 cin.tie(0); 12 int n,b; 13 cin>>n>>b; 14 int mid; 15 for(int i=1;i<=n;i++) 16 { 17 cin>>a[i]; 18 if(a[i]==b) 19 mid=i,a[i]=0; 20 else if(a[i]>b) 21 a[i]=1; 22 else 23 a[i]=-1; 24 } 25 int ans=1; 26 map<int,int>mp; 27 for(int i=mid+1;i<=n;i++) 28 { 29 a[i]+=a[i-1]; 30 if(a[i]==0) 31 { 32 ans++; 33 } 34 mp[a[i]]++; 35 } 36 for(int i=mid-1;i>=1;i--) 37 { 38 a[i]+=a[i+1]; 39 ans+=mp[-a[i]]; 40 if(a[i]==0) 41 { 42 ans++; 43 } 44 } 45 cout<<ans<<'\n'; 46 47 48 49 50 }View Code
标签:后缀,前缀,奇数,int,中位数,mid,牛客,CQOI2009,ans 来源: https://www.cnblogs.com/winfor/p/13047281.html