树状数组解法
个人遇到的问题:虽然知道这种问题首先要倒着处理出依次的真实位置。但是想法错了。。
我认为是倒着处理每个位置的真实位置为:插入的位置+当前位置之后插入位置比当前插入的位置小的数量
结果一直wa
后来找到了一组样例
6
0 1 2 0 3 4
用上面的方法位置结果实际上是错的。
是因为当某一个位置插入之后,当再次插入的位置比之前插入的位置大也会影响之前的位置。
正确方法是把所有位置置1,还是倒着处理,对于每个位置cc[i],找第一个前缀和等于cc[i]的位置,就是真实位置。找的话就用二分找。
找到值得位置后在用一次树状数组就行了。
#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5+5;
typedef long long ll;
const ll mod = 1e9+7;
int Case = 1;
int lowbit(int x) {
return x&(-x);
}
int n, m, cc[maxn], id[maxn];
struct T2 {
int T[maxn];
int query(int pos) {
int res = 0;
for (int i = pos; i >= 1; i -= lowbit(i)) {
res += T[i];
}
return res;
}
void update(int pos, int x) {
for (int i = pos; i <= n; i += lowbit(i)) {
T[i] += x;
}
}
} T2;
struct Tree {
int T[maxn];
int query(int pos) {
int res = 0;
for (int i = pos; i >= 1; i -= lowbit(i)) {
res = max(res, T[i]);
}
return res;
}
void update(int pos, int num) {
for (int i = pos; i <= n; i += lowbit(i)) {
T[i] = max(T[i], num);
}
}
}Tree;
void solve() {
scanf("%d", &n);
for(int i = 1; i <= n; i++) {
scanf("%d", &cc[i]);
cc[i]++;
T2.update(i, 1);
}
for(int i = n; i >= 1; i--) {
// int pos = T2.query(cc[i]) + cc[i];
// T2.update(pos, 1);
// id[i] = pos;
// cout<<pos<<endl;
int l = 0, r = n;
while(r-l>1) {
int mid = (r+l)/2;
if(T2.query(mid) >= cc[i]) r = mid;
else l = mid;
}
T2.update(r, -1);
id[i] = r;
}
int res;
for(int i = 1; i <= n; i++) {
int pos = id[i];
int num = Tree.query(pos-1)+1;
res = max(res, num);
Tree.update(pos, num);
printf("%d\n", res);
}
return;
}
int main() {
//g++ -std=c++11 -o2 1.cpp -o f && ./f < in.txt
//ios::sync_with_stdio(false);
#ifndef ONLINE_JUDGE
//freopen("in.txt", "r", stdin);
//freopen("out.txt","w",stdout);
#endif
while(Case--) {
solve();
}
return 0;
}
平衡树
平衡树的话套个模板就行了。。
平衡树可以得到位置i的值。然后树状数组搞一下就行了。
#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5+5;
typedef long long ll;
const ll mod = 1e9+7;
int Case = 1;
int n, m;
struct Tree {
int T[maxn];
int lowbit(int x) {
return x&(-x);
}
int query(int pos) {
int res = 0;
for (int i = pos; i >= 1; i -= lowbit(i)) {
res = max(res, T[i]);
}
return res;
}
void update(int pos, int num) {
for (int i = pos; i <= n; i += lowbit(i)) {
T[i] = max(T[i], num);
}
}
}Tree;
int cc[maxn];
struct treap {
int cnt, ch[maxn][2], sz[maxn], p[maxn], t;
void pushup(int rt) { sz[rt] = sz[ch[rt][0]] + sz[ch[rt][1]] + 1; }
void rotate(int &rt, int d) {
int v = ch[rt][d];
ch[rt][d] = ch[v][d ^ 1];
ch[v][d ^ 1] = rt;
rt = v;
}
void insert(int &rt, int x) {
if (!rt) {
rt = ++cnt;
sz[rt] = 1;
p[rt] = rand();
return;
}
int d = sz[ch[rt][0]] < x;
sz[rt]++;
insert(ch[rt][d], d ? x - 1 - sz[ch[rt][0]] : x);
if (p[rt] < p[ch[rt][d]]) rotate(rt, d), pushup(ch[rt][d ^ 1]), pushup(rt);
}
void dfs(int rt) {
if(!rt) return;
dfs(ch[rt][0]);
cc[++t] = rt;
dfs(ch[rt][1]);
}
} treap;
void solve() {
scanf("%d", &n);int root = 0;
for(int i = 1; i <= n; i++) {
int x;scanf("%d", &x);
treap.insert(root, x);
}
treap.dfs(root);
assert(treap.t == n);
int f[maxn];
for(int i = 1; i <= n; i++) {
int pos = cc[i];
//cout<<pos<<endl;
int num = Tree.query(pos)+1;
f[pos] = num;
Tree.update(pos, num);
}
for(int i = 1; i <= n; i++) {
f[i] = max(f[i-1], f[i]);
printf("%d\n", f[i]);
}
return;
}
int main() {
//g++ -std=c++11 -o2 1.cpp -o f && ./f < in.txt
//ios::sync_with_stdio(false);
#ifndef ONLINE_JUDGE
//freopen("in.txt", "r", stdin);
//freopen("out.txt","w",stdout);
#endif
while(Case--) {
solve();
}
return 0;
}