daimayuan#1004. 双端队列 (树状数组)

image
ai入队首还是队尾 只对已经放入的1到ai-1的贡献不同。 对后面的ai+1到n没有贡献。
ai+1入队尾,则ai一定在ai+1前,ai+1入队首,则ai一定在ai+1后。
所以ai入队首还是队尾看前面有多少比他小的,多少比它大的就行了。树状数组维护(权值线段树)

#include<bits/stdc++.h>
//#include <bits/extc++.h>
using namespace std;
// using namespace __gnu_cxx;
// using namespace __gnu_pbds;
#define IOS ios::sync_with_stdio(false) ,cin.tie(0), cout.tie(0);  
//#pragma GCC optimize(3,"Ofast","inline")
#define ll long long
#define ull unsigned long long
#define li __int128_t
#define PII pair<int, int>
//#define int long long
const int N = 2e5 + 5;
const int M = 1e6 + 5;
const int mod = 998244353;
const ll LNF = 0x3f3f3f3f3f3f3f3f;
const double PI = acos(-1.0);
int a[N]; int tree[N];
int lowbit( int x ) { return x & (- x); }
void update ( int i, int val) {
  for ( i; i <= N - 1; i += lowbit(i) ) tree[i] += val;
}
int query( int l, int r ) {
  int res = 0; -- l; // i 为0的前缀和就是0,,在树状数组种要特判
  if(!r) return res;
  for ( ; r >= 1; r -= lowbit(r) ) res += tree[r];
  if(!l) return res;
  for ( ; l >= 1; l -= lowbit(l) ) res -= tree[l];
  return res;

}
int main() {
  IOS
  int n; cin >> n;
  vector<int> b;
  for ( int i = 1; i <= n; ++ i ) cin >> a[i], b.push_back(a[i]);
  sort(b.begin(), b.end()); b.erase(unique(b.begin(), b.end()), b.end());
  for ( int i = 1; i <= n; ++ i ) a[i] = lower_bound(b.begin(), b.end(), a[i]) - b.begin() + 1;
  ll ans = 0;
  for ( int i = 1; i <= n; ++ i ) {
    ans += min( query(1, a[i] - 1), query( a[i] + 1, n ) );
    update(a[i], 1);
  }
  cout << ans << "\n";
  return 0;
}
posted @ 2022-06-02 21:11  qingyanng  阅读(25)  评论(0编辑  收藏  举报