結果

問題 No.121 傾向と対策:門松列(その2)
ユーザー uenokuuenoku
提出日時 2017-02-21 14:14:16
言語 C++14
(gcc 12.3.0 + boost 1.83.0)
結果
AC  
実行時間 4,436 ms / 5,000 ms
コード長 2,757 bytes
コンパイル時間 1,422 ms
コンパイル使用メモリ 116,540 KB
実行使用メモリ 128,248 KB
最終ジャッジ日時 2024-06-28 18:44:47
合計ジャッジ時間 11,829 ms
ジャッジサーバーID
(参考情報)
judge1 / judge3
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 84 ms
8,072 KB
testcase_01 AC 139 ms
10,720 KB
testcase_02 AC 10 ms
5,376 KB
testcase_03 AC 958 ms
82,504 KB
testcase_04 AC 4,436 ms
128,248 KB
testcase_05 AC 899 ms
82,372 KB
testcase_06 AC 841 ms
82,104 KB
testcase_07 AC 987 ms
82,172 KB
testcase_08 AC 998 ms
82,376 KB
権限があれば一括ダウンロードができます

ソースコード

diff #

#include "math.h"
#include <algorithm>
#include <complex>
#include <cstdio>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <string>
#include <vector>
#define ifor(i, a, b) for (int i = (a); i < (b); i++)
#define rfor(i, a, b) for (int i = (b)-1; i >= (a); i--)
#define rep(i, n) for (int i = 0; i < (n); i++)
#define rrep(i, n) for (int i = (n)-1; i >= 0; i--)
using namespace std;
typedef long double ld;
typedef long long int lli;
typedef complex<double> P;
const double eps = 1e-11;
int vex[4] = {1, 0, -1, 0};
int vey[4] = {0, 1, 0, -1};
typedef vector<double> Vec;
typedef vector<int> vec;
typedef vector<Vec> MAT;
typedef vector<vec> mat;
lli MOD = 1000000007;
template <class T>
class bit
{
public:
    vector<T> dat;
    int n;

    bit(int n) : n(n) { dat.assign(n, 0); }
    bit(int n, T ini) : n(n) { dat.assign(n, ini); }
    // sum [0,i)
    T sum(int i)
    {
        int ret = 0;
        for (--i; i >= 0; i = (i & (i + 1)) - 1)
            ret += dat[i];
        return ret;
    }
    // sum [i,j)
    T sum(int i, int j) { return sum(j) - sum(i); }
    // add x to i
    void add(int i, T x)
    {
        for (; i < n; i |= i + 1)
            dat[i] += x;
    }
};
lli n;
lli solve(vector<lli> a, lli x)
{
    rep(i, n)
    {
        a[i] *= x;
    }
    bit<lli> b(n + 20);
    map<lli, lli> loop;
    vector<pair<lli, lli>> d;
    rep(i, n)
    {
        d.push_back(make_pair(a[i], i));
        loop[a[i]]++;
    }
    sort(d.begin(), d.end());
    //a_jが中心でa_i,a_jとなるものを考える.
    lli ans = 0;
    rep(j, n)
    {
        //cout << "LOOP" << j << endl;
        lli num = d[j].first;
        //cout << num << endl;
        vector<lli> ins;
        rep(l, loop[num])
        {
            lli in = d[j].second;
            lli left = b.sum(0, in);
            lli right = b.sum(in, n + 10);
            ans += left * right;
            ins.push_back(in);
            j++;
        }
        j--;
        for (auto k : ins) {
            b.add(k, 1);
        }
    }
    // ここまででa_i == a_jも含めたものができた.
    return ans;
}
int main()
{
    cin >> n;
    vector<lli> a(n);
    rep(i, n) cin >> a[i];

    //座標圧縮
    vector<lli> b(a), left(n, 0), right(n, 0);
    sort(b.begin(), b.end());
    b.erase(unique(b.begin(), b.end()), b.end());
    rep(i, n)
    {
        a[i] = lower_bound(b.begin(), b.end(), a[i]) - b.begin();
        right[a[i]]++;
    }
    lli ans = solve(a, 1);
    ans += solve(a, -1);
    lli sum = 0;
    rep(i, n)
    {
    }
    rep(i, n)
    {
        sum -= left[a[i]] * right[a[i]];
        ans -= sum;
        left[a[i]]++;
        right[a[i]]--;
        sum += left[a[i]] * right[a[i]];
    }
    cout << ans << endl;
}
0