bzoj3173【树状数组】【平衡树】

树状数组解法
个人遇到的问题:虽然知道这种问题首先要倒着处理出依次的真实位置。但是想法错了。。
我认为是倒着处理每个位置的真实位置为:插入的位置+当前位置之后插入位置比当前插入的位置小的数量
结果一直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;
}

猜你喜欢

转载自blog.csdn.net/qq_39921637/article/details/95489962