Rinne Loves Data Structure
思路
我们插入的位置大概分了四种:
第一种
显然我们找到比当前插入的值的pre,也就是比当前节点大的最小值。
第二种
我们只要找到当前节点的suc,也就是比当前节点小的,最大值。
第三种
我们只要找到当前节点的suc,也就是比当前节点小的,最大值。
第四种
显然我们找到比当前插入的值的pre,也就是比当前节点大的最小值。
综上,一,三我们可以直接去
第二种是没有的,我们也可以直接特判,得到它的,更新
第四种是没有的,我们可以直接特判,然后得到它的,所以
插入第一个元素的时候我们既没有前驱,也没有后驱,需要单独考虑。
最后加一个相同值的判定,这道题目没有明确说明是否这n个数都是不一样的。
代码
/* Author : lifehappy */ #pragma GCC optimize(2) #pragma GCC optimize(3) #include <bits/stdc++.h> #define mp make_pair #define pb push_back #define endl '\n' using namespace std; typedef long long ll; typedef unsigned long long ull; typedef pair<int, int> pii; const double pi = acos(-1.0); const double eps = 1e-7; const int inf = 0x3f3f3f3f; inline ll read() { ll f = 1, x = 0; char c = getchar(); while(c < '0' || c > '9') { if(c == '-') f = -1; c = getchar(); } while(c >= '0' && c <= '9') { x = (x << 1) + (x << 3) + (c ^ 48); c = getchar(); } return f * x; } void print(ll x) { if(x < 10) { putchar(x + 48); return ; } print(x / 10); putchar(x % 10 + 48); } const int N = 3e5 + 10; int dep[N], n; set<int> st; int main() { // freopen("in.txt", "r", stdin); // freopen("out.txt", "w", stdout); // ios::sync_with_stdio(false), cin.tie(0), cout.tie(0); int n = read(); ll ans = 0; while(n--) { int x = read(); if(st.size() == 0) { puts("0"); st.insert(x); continue; } // auto p = lower_bound(st.begin(), st.end(), x); //用这个给tle了,不懂原理。 auto p = st.lower_bound(x); if(*p == x) { printf("%lld\n", ans); continue; } if(p == st.begin()) { dep[x] = dep[*p] + 1; ans += dep[x]; } else if(p == st.end()) { p--; dep[x] = dep[*p] + 1; ans += dep[x]; } else { dep[x] = dep[*p] + 1; p--; dep[x] = max(dep[x], dep[*p] + 1); ans += dep[x]; } st.insert(x); printf("%lld\n", ans); } return 0; }