JZOJ 1386. 排序
题目
分析
- 刚开始是想用差分数值纪录移动的差值
- 但是这不能直接一个区间直接加
- 因为影响向右的数就要减或加所以要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 }
为何要逼自己长大,去闯不该闯的荒唐