题目
分析
- 刚开始是想用差分数值纪录移动的差值
- 但是这不能直接一个区间直接加
- 因为影响向右的数就要减或加所以要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 }