题目链接:http://codeforces.com/contest/830/problem/B
题解:其实这题就是求当前大小的数到下一个大小的数直接有多少个数,这时候可以利用数据结构来查询它们之间有几个数优先往后面找如果后面没了再轮到前面找。可以开始将每个数的下表定为1然后拿掉之后就为0然后两值之间有几个数就用区间求和来求。
#include <iostream> #include <cstring> #include <cstdio> #include <algorithm> #define inf 0X3f3f3f3f using namespace std; const int M = 1e5 + 10; typedef long long ll; int a[M] , b[M]; struct TGP { int Min , pos; TGP() {} TGP(int Min , int pos):Min(Min), pos(pos) {} }; struct TnT { int l , r , sum; TGP gp; }T[M << 2]; void push_up(int i) { T[i].sum = T[i << 1].sum + T[(i << 1) | 1].sum; if(T[i << 1].gp.Min <= T[(i << 1) | 1].gp.Min) { T[i].gp = T[i << 1].gp; } else T[i].gp = T[(i << 1) | 1].gp; } void build(int l , int r , int i) { int mid = (l + r) >> 1; T[i].l = l , T[i].r = r; if(l == r) { T[i].gp.Min = a[l]; T[i].gp.pos = l; T[i].sum = 1; return ; } build(l , mid , i << 1); build(mid + 1 , r , (i << 1) | 1); push_up(i); } void update(int pos , int i) { int mid = (T[i].l + T[i].r) >> 1; if(T[i].l == T[i].r && T[i].l == pos) { T[i].gp.Min = inf; T[i].sum = 0; return ; } if(pos > mid) update(pos , (i << 1) | 1); else update(pos , i << 1); push_up(i); } TGP query(int l , int r , int i) { int mid = (T[i].l + T[i].r) >> 1; if(T[i].l == l && T[i].r == r) { return T[i].gp; } if(mid < l) return query(l , r , (i << 1) | 1); else if(mid >= r) return query(l , r , i << 1); else { TGP a1 = query(l , mid , i << 1) , a2 = query(mid + 1 , r , (i << 1) | 1); if(a1.Min > a2.Min) return a2; else return a1; } } int getsum(int l , int r , int i) { int mid = (T[i].l + T[i].r) >> 1; if(T[i].l == l && T[i].r == r) { return T[i].sum; } if(mid < l) return getsum(l , r , (i << 1) | 1); else if(mid >= r) return getsum(l , r , i << 1); else return getsum(l , mid , i << 1) + getsum(mid + 1 , r , (i << 1) | 1); } int main() { int n; scanf("%d" , &n); for(int i = 1 ; i <= n ; i++) scanf("%d" , &a[i]) , b[i] = a[i]; sort(b + 1 , b + n + 1); build(1 , n , 1); ll ans = 0; int now = 1; for(int i = 1 ; i <= n ; i++) { TGP gg = query(now , n , 1); //cout << gg.Min << ' ' << gg.pos << endl; if(gg.Min == b[i]) { ans += getsum(now , gg.pos , 1); //cout << "ans: " << ans << endl; now = gg.pos + 1; if(now > n) now = 1; update(gg.pos , 1); } else { TGP gb = query(1 , now , 1); //cout << gb.Min << ' ' << gb.pos << endl; if(gb.Min == b[i]) { ans += getsum(now , n , 1); ans += getsum(1 , gb.pos , 1); now = gb.pos + 1; if(now > n) now = 1; update(gb.pos , 1); } } } printf("%lld " , ans); return 0; }