提交人数:3
通过人数:0
题目描述
你有一个数列a_1, a_2, \dots, a_na1?,a2?,…,an?,你要模拟一个类似于快速排序的过程。有一个固定的数字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 13
发现对题目总的操作,小于等于x的树的相对顺序不会改版,
从前也讲过把操作序列转变成01序列的题,然后这个题也是。
小于等于的变成0,大的变成1
翻转就是 统计区间内又几个1,几个0,前面的一段赋值为0,后面的一段赋值为1,
求和就是,单开两个数组按顺序存两种树,求前缀和,每次作差求答案。
1 #include<bits/stdc++.h> 2 #define CLR(a,b) memset(a,b,sizeof(a)) 3 using namespace std; 4 typedef long long ll; 5 const int maxn=200010; 6 const int inf=0x3f3f3f3f; 7 ll a[maxn]; 8 struct node{ 9 ll sum,lazy; 10 }tr[maxn<<2]; 11 int n,q,pa,pb; 12 ll x,prea[maxn],preb[maxn]; 13 void init(){ 14 pa=0,pb=0; 15 } 16 void build(int o,int l,int r){ 17 if(l==r){ 18 tr[o].sum=a[l]; 19 tr[o].lazy=-1; 20 return ; 21 } 22 int mid=(l+r)>>1; 23 build(o<<1,l,mid); 24 build((o<<1)|1,mid+1,r); 25 tr[o].sum=tr[o<<1].sum+tr[(o<<1)|1].sum; 26 tr[o].lazy=-1; 27 } 28 void pushup(int o){ 29 tr[o].sum=tr[o<<1].sum+tr[o<<1|1].sum; 30 } 31 void pushdown(int o,int l,int r){ 32 if(tr[o].lazy!=-1){ 33 tr[o<<1].lazy=tr[o].lazy; 34 tr[o<<1|1].lazy=tr[o].lazy; 35 int mid=(l+r)>>1; 36 tr[o<<1].sum=tr[o].lazy*(mid-l+1); 37 tr[o<<1|1].sum=tr[o].lazy*(r-mid); 38 tr[o].lazy=-1; 39 } 40 } 41 void update(int o,int l,int r,int ql,int qr,ll val){ 42 if(ql<=l&&r<=qr){ 43 tr[o].lazy=val; 44 tr[o].sum=val*(r-l+1); 45 return; 46 } 47 pushdown(o,l,r); 48 int mid=l+((r-l)>>1); 49 if(ql<=mid)update(o<<1,l,mid,ql,qr,val); 50 if(qr>=mid+1)update(o<<1|1,mid+1,r,ql,qr,val); 51 pushup(o); 52 } 53 ll query(int o,int l,int r,int ql,int qr){ 54 if(ql<=l&&qr>=r)return tr[o].sum; 55 pushdown(o,l,r); 56 int mid=(l+r)>>1; 57 ll ans=0; 58 if(ql<=mid)ans=query(o<<1,l,mid,ql,qr); 59 if(qr>=mid+1)ans+=query(o<<1|1,mid+1,r,ql,qr); 60 return ans; 61 } 62 int op,u,v; 63 int main(){ 64 while(cin>>n>>q>>x){ 65 init(); 66 for(int i=1;i<=n;i++) 67 { 68 scanf("%lld",&a[i]); 69 if(a[i]<=x){ 70 prea[++pa]=a[i]; 71 prea[pa]+=prea[pa-1]; 72 a[i]=0; 73 }else{ 74 preb[++pb]=a[i]; 75 preb[pb]+=preb[pb-1]; 76 a[i]=1; 77 } 78 } 79 build(1,1,n); 80 while(q--) 81 { 82 scanf("%d%d%d",&op,&u,&v); 83 if(op==2){ 84 ll tep=query(1,1,n,u,v); 85 tep=v-u+1-tep; 86 if(tep>0) 87 update(1,1,n,u,u+tep-1,0); 88 if(tep<v-u+1) 89 update(1,1,n,u+tep,v,1); 90 }else if(op==1){ 91 if(u==1){ 92 ll tp=query(1,1,n,u,v); 93 ll ans=preb[tp]; 94 ans+=prea[v-tp]; 95 printf("%lld\n",ans); 96 continue; 97 } 98 ll tp1=query(1,1,n,1,u-1); 99 ll tp2=query(1,1,n,1,v); 100 ll ans=preb[tp2]-preb[tp1]; 101 tp1=u-1-tp1,tp2=v-tp2; 102 ans+=prea[tp2]-prea[tp1]; 103 printf("%lld\n",ans); 104 }else{ 105 ll tep=query(1,1,n,u,v); 106 if(tep>0) 107 update(1,1,n,u,u+tep-1,1); 108 if(tep<v-u+1) 109 update(1,1,n,u+tep,v,0); 110 } 111 } 112 } 113 }
原文:https://www.cnblogs.com/zhangbuang/p/10959004.html