[HEOI 2016] sort
[HEOI 2016] sort
解题报告
码线段树快调废我了= =
其实这题貌似暴力分很足,直接$STL$的$SORT$就能$80$
正解:
我们可以二分答案来做这道题
假设我们二分的答案为$a$,我们就可以将整个序列分为两个集合,一个是大于等于$a$的,一个是小于$a$的
那么我们就可以将大于等于$a$的赋值为$1$,小于$a$的赋值为$0$,那么对于排序,我们就变成了线段树区间覆盖,升序就将区间中所有的$0$覆盖到前面,$1$覆盖到后面,反之亦然。
最后我们查询询问位置的数,是$1$说明二分的答案小了,需要左边界右移,反之则右边界左移。
1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 using namespace std; 5 inline int read(){ 6 int sum(0); 7 char ch(getchar()); 8 for(;ch<'0'||ch>'9';ch=getchar()); 9 for(;ch>='0'&&ch<='9';sum=sum*10+(ch^48),ch=getchar()); 10 return sum; 11 } 12 int n,m,q; 13 int op[100005],l[100005],r[100005]; 14 int a[100005]; 15 int sum[400005],add[400005]; 16 inline void pushup(int i){ 17 sum[i]=sum[i<<1]+sum[i<<1|1]; 18 } 19 inline void pushdown(int i,int len){ 20 if(add[i]!=-1){ 21 add[i<<1]=add[i]; 22 add[i<<1|1]=add[i]; 23 sum[i<<1]=add[i]*(len-(len>>1)); 24 sum[i<<1|1]=add[i]*(len>>1); 25 add[i]=-1; 26 } 27 } 28 inline void build(int l,int r,int i,int x){ 29 add[i]=-1; 30 if(l==r){ 31 if(a[l]>=x) 32 sum[i]=1; 33 else 34 sum[i]=0; 35 return; 36 } 37 int mid((l+r)>>1); 38 build(l,mid,i<<1,x); 39 build(mid+1,r,i<<1|1,x); 40 pushup(i); 41 } 42 inline void update(int ll,int rr,int l,int r,int w,int i){//cout<<"update"<<ll<<' '<<rr<<' '<<l<<' '<<r<<' '<<w<<' '<<i<<endl; 43 if(ll>rr) 44 return; 45 if(ll<=l&&r<=rr){ 46 sum[i]=w*(r-l+1); 47 add[i]=w; 48 return; 49 } 50 pushdown(i,r-l+1); 51 int mid((l+r)>>1); 52 if(ll<=mid) 53 update(ll,rr,l,mid,w,i<<1); 54 if(mid<rr) 55 update(ll,rr,mid+1,r,w,i<<1|1); 56 pushup(i); 57 } 58 inline int query(int ll,int rr,int l,int r,int i){ 59 if(ll<=l&&r<=rr) 60 return sum[i]; 61 pushdown(i,r-l+1); 62 int mid((l+r)>>1),ret(0); 63 if(ll<=mid) 64 ret+=query(ll,rr,l,mid,i<<1); 65 if(mid<rr) 66 ret+=query(ll,rr,mid+1,r,i<<1|1); 67 return ret; 68 } 69 inline bool check(int x){ 70 build(1,n,1,x); 71 for(int i=1;i<=m;++i){//cout<<l[i]<<' '<<r[i]<<endl; 72 int tmp(query(l[i],r[i],1,n,1));//cout<<i<<' '<<op[i]<<' '<<l[i]<<' '<<r[i]<<endl; 73 if(op[i]==0){//cout<<r[i]-tmp+1<<' '<<r[i]<<"devide"<<l[i]<<' '<<r[i]-tmp<<endl; 74 update(l[i],r[i]-tmp,1,n,0,1); 75 if(tmp!=0) 76 update(r[i]-tmp+1,r[i],1,n,1,1); 77 } 78 else{//cout<<l[i]<<' '<<l[i]+tmp-1<<"devide"<<l[i]+tmp<<' '<<r[i]<<endl; 79 update(l[i],l[i]+tmp-1,1,n,1,1); 80 if(tmp!=r[i]-l[i]+1) 81 update(l[i]+tmp,r[i],1,n,0,1); 82 } 83 } 84 return query(q,q,1,n,1); 85 } 86 inline void ef(int l,int r){ 87 while(l+1<r){ 88 int mid((l+r)>>1); 89 if(check(mid)) 90 l=mid; 91 else 92 r=mid; 93 } 94 printf("%d",l); 95 } 96 inline int gg(){ 97 freopen("heoi2016_sort.in","r",stdin); 98 freopen("heoi2016_sort.out","w",stdout); 99 n=read(),m=read(); 100 for(int i=1;i<=n;++i) 101 a[i]=read(); 102 for(int i=1;i<=m;++i) 103 op[i]=read(),l[i]=read(),r[i]=read(); 104 q=read(); 105 ef(1,n); 106 // printf("%d",ans); 107 return 0; 108 } 109 int K(gg()); 110 int main(){;}