結果
| 問題 |
No.1031 いたずら好きなお姉ちゃん
|
| コンテスト | |
| ユーザー |
Rho
|
| 提出日時 | 2020-04-04 03:46:51 |
| 言語 | C++14 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
AC
|
| 実行時間 | 2,291 ms / 3,500 ms |
| コード長 | 3,379 bytes |
| コンパイル時間 | 2,729 ms |
| コンパイル使用メモリ | 188,032 KB |
| 実行使用メモリ | 17,780 KB |
| 最終ジャッジ日時 | 2024-10-03 03:25:08 |
| 合計ジャッジ時間 | 23,874 ms |
|
ジャッジサーバーID (参考情報) |
judge3 / judge1 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 3 |
| other | AC * 53 |
ソースコード
#include "bits/stdc++.h"
#pragma warning(disable:4996)
using namespace std;
#define int long long
#define rep(i,n) for(int i=0;i<n;i++)
typedef pair<int, int> P;
const long long mod = 1000000007;
const long long inf = 1ll << 61;
struct RMQ {
int n; vector<int>node2;
void init(int N) {
n = 1;
while (n < N)n *= 2;
node2.resize(2 * n, -inf);
}
void update(int x, int a) {
x += n - 1;
node2[x] = a;
while (x > 0) {
x = (x - 1) / 2;
node2[x] = max(node2[x * 2 + 1], node2[x * 2 + 2]);
}
}
int query2(int a, int b, int k, int l, int r) {
if (r <= a || b <= l)return -inf;
if (a <= l&&r <= b)return node2[k];
int vl = query2(a, b, k * 2 + 1, l, (l + r) / 2);
int vr = query2(a, b, k * 2 + 2, (l + r) / 2, r);
return max(vl, vr);
}
int getmax(int a, int b) {
return query2(a, b, 0, 0, n);
}
};
struct BIT {
int bit[100006];
int N;
void init(int n) {
N = n;
for (int i = 0; i <= N; i++)bit[i] = 0;
}
int sum(int i) {
int s = 0;
while (i > 0) {
s += bit[i];
i -= i&-i;
}
return s;
}
void add(int i, int x) {
while (i <= N) {
bit[i] += x;
i += i&-i;
}
}
};
int p[100005];
int n;
RMQ seg; BIT bi;
vector<P>LS, RS, v;
void input() {
cin >> n; rep(i, n)cin >> p[i];
assert(1 <= n&&n <= 100000);
set<int>S;
rep(i, n)S.insert(p[i]);
assert(S.size() == n&&*S.begin() == 1 && *S.rbegin() == n);
seg.init(n);
rep(i, n)seg.update(i, p[i]);
bi.init(n + 1);
}
int sis(int l, int r, int base) {//初項がbaseのときのISを計算
int res = 0, mn = base;
for (int i = l; i <= r; i++) {
if (mn <= p[i]) {
mn = p[i];
res++;
}
}
return res;
}
int sqrtdc(vector<P>S) {
int sqrtN = sqrt(n);
vector<P>iss[400]; vector<int>maxnum;
int K = (n + sqrtN - 1) / sqrtN;
rep(i, K) {
int l1 = i*sqrtN, r1 = min(l1 + sqrtN - 1, n - 1);
for (int j = l1; j <= r1; j++) {
iss[i].push_back(P(p[j], sis(l1, r1, p[j])));
}
iss[i].push_back(P(inf, 0));
sort(iss[i].begin(), iss[i].end());
}
int ans = 0;
rep(i, n) {
if (S[i].first > S[i].second)continue;
int L = S[i].first, R = S[i].second + 1;
int mn = 0;
for (int k = 0; k < K; k++) {
int l = k*sqrtN, r = (k + 1)*sqrtN;
if (r <= L || R <= l)continue;
if (L <= l&&r <= R) {
auto p2 = *lower_bound(iss[k].begin(), iss[k].end(), P(mn, -1));
if (p2.first != inf) {
ans += p2.second;
mn = seg.getmax(l, r);
}
}
else {
for (int j = max(l, L); j < min(R, r); j++) {
if (mn < p[j]) {
ans++; mn = p[j];
}
}
}
}
}
return ans;
}
int honsitu() {
//区間に分ける
rep(i, n)v.push_back(P(p[i], i));
sort(v.begin(), v.end());
rep(i, n) {
int s = bi.sum(v[i].second);
int lb = v[i].second, ub = n + 1;
while (ub - lb > 1) {
int mi = (ub + lb) / 2;
if (bi.sum(mi) > s)ub = mi;
else lb = mi;
}
RS.push_back(P(v[i].second + 1, lb - 1));
bi.add(v[i].second + 1, 1);
}
int ans = sqrtdc(RS);
reverse(p, p + n);
bi.init(n + 1);
rep(i, n)seg.update(i, p[i]);
rep(i, n) {
v[i].second = n - 1 - v[i].second;
int s = bi.sum(v[i].second);
int lb = v[i].second, ub = n + 1;
while (ub - lb > 1) {
int mi = (ub + lb) / 2;
if (bi.sum(mi) > s)ub = mi;
else lb = mi;
}
LS.push_back(P(v[i].second + 1, lb - 1));
bi.add(v[i].second + 1, 1);
}
ans += sqrtdc(LS);
return ans;
}
signed main() {
input();
cout << honsitu() << endl;
}
Rho