BZOJ4552:[TJOI2016&HEOI2016]排序(线段树,二分)

Description

在2016年,佳媛姐姐喜欢上了数字序列。因而他经常研究关于序列的一些奇奇怪怪的问题,现在他在研究一个难题,需要你来帮助他。
这个难题是这样子的:给出一个1到n的全排列,现在对这个全排列序列进行m次局部排序,排序分为两种:1:(0,l,r)表示将区间[l,r]的数字升序排序2:(1,l,r)表示将区间[l,r]的数字降序排序
最后询问第q位置上的数字。

Input

输入数据的第一行为两个整数n和m。n表示序列的长度,m表示局部排序的次数。1 <= n, m <= 10^5第二行为n个整数,表示1到n的一个全排列。
接下来输入m行,每一行有三个整数op, l, r, op为0代表升序排序,op为1代表降序排序, l, r 表示排序的区间。
最后输入一个整数q,q表示排序完之后询问的位置, 1 <= q <= n。1 <= n <= 10^5,1 <= m <= 10^5

Output

输出数据仅有一行,一个整数,表示按照顺序将全部的部分排序结束后第q位置上的数字。

Sample Input

6 3
1 6 2 5 3 4
0 1 4
1 3 6
0 2 4
3

Sample Output

5

Solution

也就只有刷刷水才能挽救一下博客文章数量这样子

二分最终的答案是不是小于等于$mid$,然后把小于等于$mid$的置为$0$,大于的置为$1$。

然后区间$sort$就可以查询一下区间$1$的个数然后用线段树区间覆盖来搞。

Code

 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdio>
 4 #define N (100009)
 5 using namespace std;
 6 
 7 struct Edge{int val,down;}Segt[N<<2];
 8 int n,m,p,a[N],opt[N],l[N],r[N];
 9 
10 void Pushdown(int now,int l,int r)
11 {
12     if (Segt[now].down!=-1)
13     {
14         int mid=(l+r)>>1;
15         Segt[now<<1].down=Segt[now<<1|1].down=Segt[now].down;
16         Segt[now<<1].val=(mid-l+1)*Segt[now].down;
17         Segt[now<<1|1].val=(r-mid)*Segt[now].down;
18         Segt[now].down=-1;
19     }
20 }
21 
22 void Update(int now,int l,int r,int l1,int r1,int k)
23 {
24     if (l>r1 || r<l1) return;
25     if (l1<=l && r<=r1)
26     {
27         Segt[now].val=(r-l+1)*k;
28         Segt[now].down=k;
29         return;
30     }
31     Pushdown(now,l,r);
32     int mid=(l+r)>>1;
33     Update(now<<1,l,mid,l1,r1,k);
34     Update(now<<1|1,mid+1,r,l1,r1,k);
35     Segt[now].val=Segt[now<<1].val+Segt[now<<1|1].val;
36 }
37 
38 int Query(int now,int l,int r,int l1,int r1)
39 {
40     if (l>r1 || r<l1) return 0;
41     if (l1<=l && r<=r1) return Segt[now].val;
42     Pushdown(now,l,r);
43     int mid=(l+r)>>1;
44     return Query(now<<1,l,mid,l1,r1)+Query(now<<1|1,mid+1,r,l1,r1);
45 }
46 
47 bool check(int x)
48 {
49     for (int i=1; i<=n*4; ++i) Segt[i].val=0, Segt[i].down=-1;
50     for (int i=1; i<=n; ++i)
51         Update(1,1,n,i,i,a[i]>x);
52     for (int i=1; i<=m; ++i)
53     {
54         int sum=Query(1,1,n,l[i],r[i]);
55         if (opt[i]==0) Update(1,1,n,r[i]-sum+1,r[i],1), Update(1,1,n,l[i],r[i]-sum,0);
56         else Update(1,1,n,l[i],l[i]+sum-1,1), Update(1,1,n,l[i]+sum,r[i],0);
57     }
58     return !Query(1,1,n,p,p);
59 }
60 
61 int main()
62 {
63     scanf("%d%d",&n,&m);
64     for (int i=1; i<=n; ++i)
65         scanf("%d",&a[i]);
66     for (int i=1; i<=m; ++i)
67         scanf("%d%d%d",&opt[i],&l[i],&r[i]);
68     scanf("%d",&p);
69     int l=1,r=n,ans=-1;
70     while (l<=r)
71     {
72         int mid=(l+r)>>1;
73         if (check(mid)) r=mid-1,ans=mid;
74         else l=mid+1;
75     }
76     printf("%d\n",ans);
77 }
posted @ 2018-12-18 21:26  Refun  阅读(185)  评论(0编辑  收藏  举报