题目:有一个圈,可以从某个位置取球,给出原有的顺序,有三种操作,左旋一次,右旋一次,取球,要求按顺序取球,问需要操作多少次
显然操作是确定的,每次将目标球旋转过来,找出左旋和右旋操作少的,然后取球。
每次旋转后相对距离不变,每次记录某个区间删掉了多少,就可以查询了。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 6 using namespace std; 7 #define lson l, m, rt<<1 8 #define rson m + 1, r, rt<<1|1 9 typedef long long ll; 10 const int maxn = 1e5 + 5; 11 int n, pos[maxn], sum[maxn << 2]; 12 ll ans; 13 void update(int p, int l, int r, int rt){ 14 sum[rt]++; 15 if (l == r) return; 16 int m = (l + r) >> 1; 17 if (p <= m) update(p, lson); 18 else update(p, rson); 19 } 20 int query(int L, int R, int l, int r, int rt){ 21 if (L > R) return 0; 22 if (L <= l && R >= r){ 23 return sum[rt]; 24 } 25 int m = (l + r) >> 1; 26 int ret = 0; 27 if (L <= m) ret += query(L, R, lson); 28 if (R > m) ret += query(L, R, rson); 29 return ret; 30 } 31 int main(){ 32 int x; 33 while (~scanf("%d", &n) && n){ 34 ans = 0; 35 memset(sum, 0, sizeof(sum)); 36 for (int i = 0; i < n; ++i){ 37 scanf("%d", &x); 38 pos[x] = i + 1; 39 } 40 int pre = 0, q, c, lx, rx; 41 for (int i = 1; i <= n; ++i){ 42 x = pos[i]; 43 if (x > pre){ 44 q = query(pre + 1, x, 1, n, 1); 45 lx = x - pre - 1 - q; 46 rx = n - i + 1 - lx; 47 } 48 else{ 49 q = query(x + 1, pre - 1, 1, n, 1); 50 rx = pre - x - q; 51 lx = n - i + 1 - rx; 52 } 53 //cout << " lx = " << lx << " rx = " << rx << endl; 54 //int lx = x - 1 - query(1, x - 1, 1, n, 1); 55 //int rx = n - x + 1 - query(x + 1, n, 1, n, 1); 56 ans += min(lx, rx) + 1; 57 pre = x; 58 update(x, 1, n, 1); 59 } 60 printf("%lld ", ans); 61 } 62 return 0; 63 }