結果
| 問題 |
No.992 最長増加部分列の数え上げ
|
| コンテスト | |
| ユーザー |
koi_kotya
|
| 提出日時 | 2020-02-14 23:17:09 |
| 言語 | C++14 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
WA
|
| 実行時間 | - |
| コード長 | 3,782 bytes |
| コンパイル時間 | 1,801 ms |
| コンパイル使用メモリ | 188,048 KB |
| 実行使用メモリ | 28,472 KB |
| 最終ジャッジ日時 | 2024-10-06 13:17:50 |
| 合計ジャッジ時間 | 11,175 ms |
|
ジャッジサーバーID (参考情報) |
judge4 / judge2 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 3 |
| other | AC * 40 WA * 2 |
ソースコード
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> P;
ll const mod = 1e9+7;
#define p_ary(ary,a,b) do { cout << "["; for (int count = (a);count < (b);++count) cout << ary[count] << ((b)-1 == count ? "" : ", "); cout << "]\n"; } while(0)
#define p_map(map,it) do {cout << "{";for (auto (it) = map.begin();;++(it)) {if ((it) == map.end()) {cout << "}\n";break;}else cout << "" << (it)->first << "=>" << (it)->second << ", ";}}while(0)
struct SegmentTree {
private:
int n;
vector<int> node;
public:
SegmentTree(vector<int> v) {
int sz = v.size();
n = 1;
while (n < sz) n *= 2;
node.resize(2*n-1,0);
for (int i = 0;i < sz;++i) node[i+n-1] = v[i];
for (int i = n-2;i >= 0;--i) node[i] = max(node[2*i+1],node[2*i+2]);
}
void update(int x,int val) {
x += (n-1);
node[x] = val;
while (x > 0) {
x = (x-1)/2;
node[x] = max(node[2*x+1],node[2*x+2]);
}
}
int getmax(int a,int b,int k = 0,int l = 0,int r = -1) {
if (r < 0) r = n;
if (r <= a || b <= l) return 0;
if (a <= l && r <= b) return node[k];
int vl = getmax(a,b,2*k+1,l,(l+r)/2);
int vr = getmax(a,b,2*k+2,(l+r)/2,r);
return max(vl,vr);
}
// [a,b)でxより大きい要素の最左位置
int find(int a,int b,int x,int k = 0,int l = 0,int r = -1) {
if (r < 0) r = n;
if (r <= a || b <= l || node[k] <= x) return -1;
if (k >= n-1) return k-n+1;
int vl = find(a,b,x,2*k+1,l,(l+r)/2);
if (vl != -1) return vl;
return find(a,b,x,2*k+2,(l+r)/2,r);
}
};
struct BinaryIndexedTree {
private:
int n,b;
vector<ll> bit;
public:
BinaryIndexedTree(int n_) {
n = n_+10;
b = 1;
while (b < n) b <<= 1;
b >>= 1;
bit = vector<ll>(n,0);
}
void add(int a,ll w) {
a++;
for (int x = a;x < n;x += x&-x) bit[x] += w;
}
ll sum(int a) {
a++;
ll ret = 0;
for (int x = a;x > 0;x -= x&-x) ret += bit[x];
return ret;
}
void update(int a,ll w) {
// a++;
ll v = w-sum(a)+sum(a-1);
add(a,v);
}
int lower_bound(int w) {
if (w <= 0) return 0;
int x = 0;
for (int k = b;k > 0;k /= 2) {
if (x+k < n && bit[x+k] < w) {
w -= bit[x+k];
x += k;
}
}
return x;
}
};
int main() {
int n;
cin >> n;
vector<int> a(n);
for (int i = 0;i < n;++i) cin >> a[i];
map<int,int> mp;
for (int i = 0;i < n;++i) mp[a[i]] = 0;
{
int i = 1;
for (auto& p : mp) {
p.second = i;
i++;
}
}
vector<int> b(n),c(n);
for (int i = 0;i < n;++i) b[i] = mp[a[i]];
SegmentTree seg(vector<int>(n+1,0));
for (int i = 0;i < n;++i) {
c[i] = seg.getmax(0,b[i])+1;
seg.update(b[i],c[i]);
}
BinaryIndexedTree bit(n);
vector<vector<pair<int,ll>>> p(n+1);
p[0].push_back(make_pair(-1,1));
for (int i = 0;i < n;++i) p[c[i]].push_back(make_pair(i,0));
for (int i = 0;i < n;++i) {
int j = 0,m = p[i].size();
for (pair<int,ll>& q : p[i+1]) {
while (j < m && p[i][j].first < q.first) {
bit.add((i ? b[p[i][j].first] : 0),p[i][j].second);
j++;
}
q.second = bit.sum(b[q.first])%mod;
}
if (i) for (pair<int,ll>& q : p[i]) bit.update(b[q.first],0);
else bit.update(0,0);
}
int mx = 0;
for (int i = 0;i < n;++i) mx = max(c[i],mx);
ll ans = 0;
for (auto q : p[mx]) (ans += q.second) %= mod;
cout << ans << endl;
}
koi_kotya