HDU 5649 DZY Loves Sorting 二分+线段树
DZY Loves Sorting
题目连接:
http://acm.hdu.edu.cn/showproblem.php?pid=5649
Description
DZY has a sequence a[1..n]. It is a permutation of integers 1∼n.
Now he wants to perform two types of operations:
0lr: Sort a[l..r] in increasing order.
1lr: Sort a[l..r] in decreasing order.
After doing all the operations, he will tell you a position k, and ask you the value of a[k].
Input
First line contains t, denoting the number of testcases.
t testcases follow. For each testcase:
First line contains n,m. m is the number of operations.
Second line contains n space-separated integers a[1],a[2],⋯,a[n], the initial sequence. We ensure that it is a permutation of 1∼n.
Then m lines follow. In each line there are three integers opt,l,r to indicate an operation.
Last line contains k.
(1≤t≤50,1≤n,m≤100000,1≤k≤n,1≤l≤r≤n,opt∈{0,1}. Sum of n in all testcases does not exceed 150000. Sum of m in all testcases does not exceed 150000)
Output
For each testcase, output one line - the value of a[k] after performing all m operations.
Sample Input
1
6 3
1 6 2 5 3 4
0 1 4
1 3 6
0 2 4
3
Sample Output
5
Hint
题意
给你n个数1~n的排列,然后有两个操作
1.将[l,r]里面的数按照升序排序
2.将[l,r]里面的数按照降序排序
给你一个k
问你a[k]是多少
题解:
二分答案
每次二分之后,将大于等于mid的置为1,小于的置为0
然后现在升序就很简单了,因为只有0和1,那么把0放在这个区间的前面,把1放在后面就好了
降序同理
然后最后看看a[k]是否等于1就好了
这样复杂度就是mlognlogn的。
涨姿势了
代码
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5+7;
int op[maxn],ql[maxn],qr[maxn],n,m,k,a[maxn];
typedef int SgTreeDataType;
struct treenode
{
int L , R ;
SgTreeDataType sum , lazy;
void update(SgTreeDataType v)
{
sum = (R-L+1)*v;
lazy = v;
}
};
treenode tree[maxn*4];
inline void push_down(int o)
{
SgTreeDataType lazyval = tree[o].lazy;
if(lazyval!=-1)
{
tree[2*o].update(lazyval) ; tree[2*o+1].update(lazyval);
tree[o].lazy = -1;
}
}
inline void push_up(int o)
{
tree[o].sum = tree[2*o].sum + tree[2*o+1].sum;
}
inline void build_tree(int L , int R , int o)
{
tree[o].L = L , tree[o].R = R,tree[o].sum = 0;
tree[o].lazy = -1;
if (R > L)
{
int mid = (L+R) >> 1;
build_tree(L,mid,o*2);
build_tree(mid+1,R,o*2+1);
}
}
inline void update(int QL,int QR,SgTreeDataType v,int o)
{
int L = tree[o].L , R = tree[o].R;
if (QL <= L && R <= QR) tree[o].update(v);
else
{
push_down(o);
int mid = (L+R)>>1;
if (QL <= mid) update(QL,QR,v,o*2);
if (QR > mid) update(QL,QR,v,o*2+1);
push_up(o);
}
}
inline SgTreeDataType query(int QL,int QR,int o)
{
int L = tree[o].L , R = tree[o].R;
if (QL <= L && R <= QR) return tree[o].sum;
else
{
push_down(o);
int mid = (L+R)>>1;
SgTreeDataType res = 0;
if (QL <= mid) res += query(QL,QR,2*o);
if (QR > mid) res += query(QL,QR,2*o+1);
push_up(o);
return res;
}
}
bool check(int mid)
{
build_tree(1,n,1);
for(int i=1;i<=n;i++)
if(a[i]>=mid)update(i,i,1,1);
else update(i,i,0,1);
for(int i=1;i<=m;i++)
{
int x = query(ql[i],qr[i],1);
if(op[i]==0)
{
x=qr[i]-ql[i]+1-x;
update(ql[i],ql[i]+x-1,0,1);
update(ql[i]+x,qr[i],1,1);
}
else
{
update(ql[i],ql[i]+x-1,1,1);
update(ql[i]+x,qr[i],0,1);
}
}
if(query(k,k,1)==1)return true;
return false;
}
void solve()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
for(int i=1;i<=m;i++)
scanf("%d%d%d",&op[i],&ql[i],&qr[i]);
scanf("%d",&k);
int l=1,r=n,ans=0;
while(l<=r)
{
int mid=(l+r)/2;
if(check(mid))l=mid+1,ans=mid;
else r=mid-1;
}
cout<<ans<<endl;
}
int main()
{
int t;scanf("%d",&t);
while(t--)solve();
}