题意 : 给你N张牌,操作为拿起牌顶的牌,若当前牌的数值是最小的,就扔掉它,否则将牌放到牌堆底,问扔完所有牌需要多少次操作。
这个题肯定是从小到大删除,可以用一个 vector 保存每一个数的下标然后给每一个数的下标从小到大排个序(这样可以用O(1)时间内找到要删掉下一个的位置 ),用线段树或者树状数组维护每个区间内有多少个数没有背删去 (单点修改,区间查询)。
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#define ll long long
using namespacestd;
const int maxn =1e5 + 10;
struct node {
int l,r;
int sum;
}tr[maxn <<2];
struct point {
int pos;
int cnt;
};
ll ans = 0;
vector <int> a[maxn];
void build (int l,int r,int root) {
tr[root].l = l;
tr[root].r = r;
if (l == r) {
tr[root].sum =1;
return;
}
int mid = (l + r) >>1;
build(l, mid, root <<1);
build(mid +1, r, root << 1 |1);
tr[root].sum =tr[root << 1].sum +tr[root << 1 |1].sum;
// return ;
}
void update (int pos,int root) {
if (tr[root].l ==tr[root].r) {
tr[root].sum =0;
return;
}
int mid = (tr[root].l +tr[root].r) >>1;
if (pos > mid) update(pos, root << 1 | 1);
else update(pos, root << 1);
tr[root].sum =tr[root << 1].sum +tr[root << 1 |1].sum;
}
int query (int l,int r,int root) {
if (l > r)return 0;
if (tr[root].l >= l &&tr[root].r <= r) {
returntr[root].sum;
}
int mid = (tr[root].l +tr[root].r) >>1;
if (l > mid)return query(l, r, root <<1 | 1);
else if (r <= mid) returnquery(l, r, root << 1);
else return query(l, r, root <<1) + query(l, r, root <<1 | 1);
}
int main () {
ios_base ::sync_with_stdio(false);
int n;
cin >> n;
build(1, n,1);
int mi =maxn;
for (int i =1;i <= n; ++ i) {
int x;
cin >> x;
mi = min (mi,x);
a[x].push_back (i);
}
for (int i = mi;i <maxn; ++ i) {
if (a[i].size()){
// cout << i << ' ' << a[i][0] << endl;
sort (a[i].begin(),a[i].end());
}
}
int pos =0;
for (int i = mi;i <maxn; ++ i) {
if (a[i].size ()) {
int u =a[i].size();
int cnt =0;
int j =lower_bound (a[i].begin(),a[i].end(),pos) - a[i].begin();
// cout << j << ' ' << a[i][j] << ' ';
if (j != u){
if (pos !=a[i][j])
ans +=query(pos + 1,a[i][j],1);
}
else {
j = 0;
ans +=query(pos + 1, n,1);
ans +=query(1,a[i][j],1);
}
// cout << ans << endl;
update(a[i][j],1);
pos = a[i][j];
for (int k =0;k < u - 1;++k) {
if (j != u -1) {
j ++;
ans +=query(pos + 1,a[i][j],1);
update(a[i][j],1);
pos = a[i][j];
}
else {
j = 0;
ans +=query(1,a[i][j],1);
ans +=query(pos + 1, n,1);
pos = a[i][j];
update(a[i][j],1);
}
}
}
}
cout <<ans << endl;
return0;
}