JZOJ 1386. 排序

题目

Description

  你收到一项对数组进行排序的任务,数组中是1到N个一个排列。你突然想出以下一种特别的排序方法,分为以下N个阶段:
  •阶段1,把数字1通过每次交换相邻两个数移到位置1;
  •阶段2,用同样的方法把N移到位置N;
  •阶段3,把数字2移到位置2处;
  •阶段4,把数字N-1移到位置N-1处;
  •依此类推。
  换句话说,如果当前阶段为奇数,则把最小的未操作的数移到正确位置上,如果阶段为偶数,则把最大的未操作的数移到正确位置上。
  写一个程序,给出初始的排列情况,计算每一阶段交换的次数。
 

Input

  第一行包含一个整数N(1<=N<=100000),表示数组中元素的个数。
  接下来N行每行一个整数描述初始的排列情况。

Output

  输出每一阶段的交换次数。
 

Sample Input

输入1:
3
2
1
3


输入2:
5
5
4
3
2
1

输出3:
7
5
4
3
7
1
2
6

Sample Output

输出1:
1
0
0

输出2:
4
3
2
1
0

输出3:
4
2
3
0
2
1
0
 

Data Constraint

 
 

Hint

【数据范围】
  70%的数据N<=100

分析

 

  • 刚开始是想用差分数值纪录移动的差值
  • 但是这不能直接一个区间直接加
  • 因为影响向右的数就要减或加所以要n
  • 我们认真思考,答案其实不就是前面或后面还未移动的个数
  • 向前移动的就数前面的,不然数后面
  • 线段树区间查询,单点修改

代码

 1 #include<iostream>
 2 using namespace std;
 3 int a[100001],to[100001],bj[100001];
 4 struct sb
 5 {
 6     int l,r,w;
 7 }t[100001*4];
 8 void build(int k,int a,int b)
 9 {
10     t[k].l=a; t[k].r=b;
11     if (a==b) {
12         t[k].w=1;
13         return;
14     }
15     int mid=a+b>>1;
16     build(k<<1,a,mid);
17     build(k<<1|1,mid+1,b);
18     t[k].w=t[k<<1].w+t[k<<1|1].w;
19 }
20 int check(int x,int y,int k)
21 {
22     if (t[k].l==x&&t[k].r==y)
23         return t[k].w;
24     int mid=(t[k].l+t[k].r)/2;
25     if (y<=mid) return check(x,y,k*2);
26     else if (x>mid) return check(x,y,k*2+1);
27     else
28         return check(x,mid,k*2)+check(mid+1,y,k*2+1);
29 }
30 void change(int k,int mb)
31 {
32     if (t[k].l<=mb&&t[k].r>=mb)
33         t[k].w--;
34     if (t[k].l==t[k].r) return;
35     int mid=t[k].l+t[k].r>>1;
36     if (mb<=mid) change(k<<1,mb);
37     else change(k<<1|1,mb);
38 }
39 int main ()
40 {
41     int n;
42     cin>>n;
43     for (int i=1;i<=n;i++) cin>>a[i],to[a[i]]=i;
44     build(1,1,n);
45     int tot=0,i=1,j=n;
46     while (++tot<=n)
47     {
48         if (tot%2==1)
49         {
50             int wz=to[i],ans=check(1,wz,1)-1;
51             if (ans<0) ans=0;
52             cout<<ans<<endl;
53             change(1,wz);
54             i++;
55         }
56         else
57         {
58             int wz=to[j],ans=check(wz,n,1)-1;
59             if (ans<0) ans=0;
60             cout<<ans<<endl;
61             change(1,wz);
62             j--;
63         }
64     }
65 }

猜你喜欢

转载自www.cnblogs.com/zjzjzj/p/11318872.html
今日推荐