Sorting(好题)
Sorting
https://www.zhixincode.com/contest/21/problem/I?problem_id=324
题目描述
你有一个数列a_1, a_2, \dots, a_na1,a2,…,an,你要模拟一个类似于快速排序的过程。有一个固定的数字xx。
你要支持三种操作:
- 询问区间[l, r][l,r]之间的元素的和,也就是\sum_{i=l}^r a_i∑i=lrai。
- 对区间[l,r][l,r]进行操作,也就是说你把区间中所有的数字拿出来,然后把小于等于xx的数字按顺序放在左边,把大于xx的数字按顺序放在右边,把这些数字接起来,放回到数列中。比如说x=3x=3,你的区间里的数字是1,5,3,2,41,5,3,2,4,那么操作完之后区间里面的数字变为1,3,2,5,41,3,2,5,4。
- 对区间[l,r][l,r]进行操作,也就是说你把区间中所有的数字拿出来,然后把大于xx的数字按顺序放在左边,把小于等于xx的数字按顺序放在右边,把这些数字接起来,放回到数列中。
输入描述
第一行三个整数n, q, x ( 1\leq n, q \leq 2*10^5, 0\leq x\leq 10^9)n,q,x(1≤n,q≤2∗105,0≤x≤109)表示元素的个数和询问的个数。
接下来一行nn个整数a_1, a_2, \dots, a_n(1\leq a_i\leq 10^9)a1,a2,…,an(1≤ai≤109)。
接下来qq行,每行三个正整数p, l, r (1\leq p\leq 3), 1\leq l\leq r\leq np,l,r(1≤p≤3),1≤l≤r≤n表示操作种类和区间。
输出描述
对于每个第一种操作,输出一行,表示答案。
样例输入 1
5 9 3 1 5 3 2 4 1 1 5 2 1 5 1 1 1 1 2 2 1 3 3 1 4 4 1 5 5 3 3 5 1 1 4
样例输出 1
15 1 3 2 5 4
15
首先,排序后小于等于x和大于x的数字的相对顺序是不变的,所以我们可以用0和1分别代替小于等于x和大于x的值。
先记录下小于等于x的数字和大于x的数字的前缀和,然后当区间修改的时候,我们就可以用前缀和来计算区间的值
区间修改的过程:当p==2时,把区间前半部分赋值为0,后半部分赋值为1,p==3时相反
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 #define lson l,mid,rt<<1 5 #define rson mid+1,r,rt<<1|1 6 #define maxn 200005 7 8 int n,q; 9 ll x; 10 11 int tree[maxn<<3],lazy[maxn<<3]; 12 ll a[maxn]; 13 14 //tree中记录了1的个数 15 16 void push_up(int rt){ 17 tree[rt]=tree[rt<<1]+tree[rt<<1|1]; 18 } 19 20 void build(int l,int r,int rt){ 21 lazy[rt]=-1; 22 if(l==r){ 23 if(a[l]<=x) tree[rt]=0; 24 else tree[rt]=1; 25 return; 26 } 27 int mid=l+r>>1; 28 build(lson); 29 build(rson); 30 push_up(rt); 31 } 32 33 void push_down(int len,int rt){ 34 if(lazy[rt]!=-1){ 35 if(lazy[rt]==0){ 36 lazy[rt<<1]=0; 37 lazy[rt<<1|1]=0; 38 tree[rt<<1]=0; 39 tree[rt<<1|1]=0; 40 } 41 else{ 42 lazy[rt<<1]=1; 43 lazy[rt<<1|1]=1; 44 tree[rt<<1]=len-len/2; 45 tree[rt<<1|1]=len/2; 46 } 47 lazy[rt]=-1; 48 } 49 } 50 51 //区间置0和置1 52 void add(int L,int R,int v,int l,int r,int rt){ 53 if(L<=l&&R>=r){ 54 if(v==0) tree[rt]=0; 55 else tree[rt]=r-l+1; 56 lazy[rt]=v; 57 push_down(r-l+1,rt); 58 return; 59 } 60 push_down(r-l+1,rt); 61 int mid=l+r>>1; 62 if(L<=mid) add(L,R,v,lson); 63 if(R>mid) add(L,R,v,rson); 64 push_up(rt); 65 } 66 67 int query(int L,int R,int l,int r,int rt){///查询在L前面1的数量 68 if(L<=l&&R>=r){ 69 return tree[rt]; 70 } 71 push_down(r-l+1,rt); 72 int mid=l+r>>1; 73 int ans=0; 74 if(L<=mid) ans+=query(L,R,lson); 75 if(R>mid) ans+=query(L,R,rson); 76 push_up(rt); 77 return ans; 78 } 79 80 ll small[maxn],big[maxn]; 81 82 int main(){ 83 std::ios::sync_with_stdio(false); 84 cin>>n>>q>>x; 85 int s_co=1,b_co=1; 86 for(int i=1;i<=n;i++){ 87 cin>>a[i]; 88 if(a[i]<=x) small[s_co]=small[s_co-1]+a[i],s_co++; 89 else big[b_co]=big[b_co-1]+a[i],b_co++; 90 } 91 build(1,n,1); 92 int p,l,r; 93 for(int i=1;i<=q;i++){ 94 cin>>p>>l>>r; 95 if(p==1){ 96 int one1,one2,one,zero1,zero2,zero; 97 one1=query(1,r,1,n,1); 98 if(1>l-1) one2=0; 99 else one2=query(1,l-1,1,n,1); 100 zero1=r-one1; 101 if(1>l-1) zero2=0; 102 else zero2=l-1-one2; 103 cout<<small[zero1]-small[zero2]+big[one1]-big[one2]<<endl; 104 } 105 else if(p==2){ 106 int one=query(l,r,1,n,1); 107 int zero=r-l+1-one; 108 if(l<=l+zero-1) add(l,l+zero-1,0,1,n,1); 109 add(l+zero,r,1,1,n,1); 110 } 111 else{ 112 int one=query(l,r,1,n,1); 113 int zero=r-l+1-one; 114 if(l<=l+one-1) add(l,l+one-1,1,1,n,1); 115 add(l+one,r,0,1,n,1); 116 } 117 } 118 }
posted on 2019-01-25 12:25 Fighting_sh 阅读(220) 评论(0) 编辑 收藏 举报