洛谷 2824 [HEOI2016/TJOI2016]排序

【题意概述】

  对一个1到n的排列做m次区间排序,最后询问位置q上面的数。

【题解】

  区间排序的效率是nlogn,所以暴力做的话效率是mnlogn,显然达不到要求。

  我们考虑二分答案。如果某个位置的数比mid小,就设为0,如果么某个位置的数大于等于mid,就设为1.  check的时候我们只需对01序列排序就好了,这个可以用线段树做到logn.

  如果排序后位置q的数为1,那么就表示原来这里的数大于等于mid,所以我们要挪动l,否则挪动r.

  总的时间复杂度为m*logn*logn

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #define LL long long
 5 #define rg register
 6 #define N 30010
 7 #define ls (u<<1)
 8 #define rs (u<<1|1)
 9 #define len(x) (a[x].r-a[x].l+1)
10 using namespace std;
11 int n,m,v[N],l,r,mid,pos;
12 struct tree{
13     int l,r,c0,c1,num; bool same;
14 }a[N<<2];
15 struct opt{
16     int l,r,type;
17 }b[N];
18 inline int read(){
19     int k=0,f=1; char c=getchar();
20     while(c<'0'||c>'9')c=='-'&&(f=-1),c=getchar();
21     while('0'<=c&&c<='9')k=k*10+c-'0',c=getchar();
22     return k*f;
23 }
24 void build(int u,int l,int r){
25     a[u].l=l; a[u].r=r; a[u].same=0; a[u].c0=a[u].c1=0;
26     if(l<r){
27         int mid=(l+r)>>1;
28         build(ls,l,mid); build(rs,mid+1,r); 
29         a[u].c0=a[ls].c0+a[rs].c0; a[u].c1=a[ls].c1+a[rs].c1;
30     }
31     else{
32         if(v[l]>=mid) a[u].c1=1,a[u].c0=0;
33         else a[u].c0=1,a[u].c1=0;
34     }
35 }
36 inline void pushdown(int u){
37     a[u].same=0; a[ls].same=a[rs].same=1;
38     a[ls].num=a[rs].num=a[u].num;
39     if(!a[u].num) a[ls].c0=len(ls),a[ls].c1=0,a[rs].c0=len(rs),a[rs].c1=0;
40     else a[ls].c0=0,a[ls].c1=len(ls),a[rs].c0=0,a[rs].c1=len(rs);
41 }
42 void update(int u,int l,int r,int num){
43     if(l<=a[u].l&&a[u].r<=r){
44         a[u].same=1; a[u].num=num;
45         if(num==1) a[u].c1=len(u),a[u].c0=0;
46         else a[u].c0=len(u),a[u].c1=0;
47         return;
48     }
49     if(a[u].same) pushdown(u);
50     int mid=(a[u].l+a[u].r)>>1;
51     if(l<=mid) update(ls,l,r,num);
52     if(r>mid) update(rs,l,r,num);
53     a[u].c0=a[ls].c0+a[rs].c0;
54     a[u].c1=a[ls].c1+a[rs].c1;
55 }
56 int query0(int u,int l,int r){
57     if(l<=a[u].l&&a[u].r<=r) return a[u].c0;
58     if(a[u].same) pushdown(u);
59     int mid=(a[u].l+a[u].r)>>1,ret=0;
60     if(l<=mid) ret=query0(ls,l,r);
61     if(r>mid) ret+=query0(rs,l,r);
62     return ret; 
63 }
64 int query1(int u,int l,int r){
65     if(l<=a[u].l&&a[u].r<=r) return a[u].c1;
66     if(a[u].same) pushdown(u);
67     int mid=(a[u].l+a[u].r)>>1,ret=0;
68     if(l<=mid) ret=query1(ls,l,r);
69     if(r>mid) ret+=query1(rs,l,r);
70     return ret; 
71 }
72 inline bool check(){
73     build(1,1,n); int r0=0,r1=0;
74     for(rg int i=1;i<=m;i++){
75         r0=query0(1,b[i].l,b[i].r); r1=query1(1,b[i].l,b[i].r);
76         if(b[i].type==0) update(1,b[i].l,b[i].l+r0-1,0),update(1,b[i].l+r0,b[i].r,1);
77         else update(1,b[i].l,b[i].l+r1-1,1),update(1,b[i].l+r1,b[i].r,0);
78     }
79     r0=query0(1,pos,pos); r1=query1(1,pos,pos);
80     return r1>0;
81 }
82 int main(){
83     n=read(); m=read();
84     for(rg int i=1;i<=n;i++) v[i]=read();
85     for(rg int i=1;i<=m;i++) b[i].type=read(),b[i].l=read(),b[i].r=read();
86     pos=read();
87     l=1,r=n+1;
88     while(l+1<r){
89         mid=(l+r)>>1;
90         if(check()) l=mid; else r=mid;
91     }
92     printf("%d\n",l);
93 }
View Code

 

posted @ 2018-08-24 10:38  Driver_Lao  阅读(238)  评论(0编辑  收藏  举报