题意:有一个n的某个排列,要求资瓷两个操作:
0 l r表示将[l,r]这个区间按升序排序
1 l r降序排序
最后问位置q上的数是多少
分析:这题题解好劲啊!!!
首先二分一下答案(蒟蒻表示根本想不到)
判断ans是否不小于mid
若a[i]<mid则a[i]=0否则a[i]=1
然后用线段树维护一下就好了
代码:
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#define N 200005
using namespace std;
int n,m,a[N];
struct quer{int op,l,r;}q[N];
struct tree{int l,r,tag,s0,s1;}t[N*10];
void pushdown(int d)
{
if (t[d].tag==-1||t[d].l==t[d].r) return;
if (t[d].tag==0)
{
t[d*2].tag=t[d*2+1].tag=0;
t[d*2].s1=t[d*2+1].s1=0;
t[d*2].s0=t[d*2].r-t[d*2].l+1;
t[d*2+1].s0=t[d*2+1].r-t[d*2+1].l+1;
t[d].tag=-1;
}else
{
t[d*2].tag=t[d*2+1].tag=1;
t[d*2].s0=t[d*2+1].s0=0;
t[d*2].s1=t[d*2].r-t[d*2].l+1;
t[d*2+1].s1=t[d*2+1].r-t[d*2+1].l+1;
t[d].tag=-1;
}
}
void updata(int d)
{
t[d].s0=t[d*2].s0+t[d*2+1].s0;
t[d].s1=t[d*2].s1+t[d*2+1].s1;
}
void build(int d,int l,int r,int p)
{
t[d].l=l;
t[d].r=r;
t[d].s0=t[d].s1=0;
t[d].tag=-1;
if (l==r)
{
if (a[l]<p) t[d].s0++;
else t[d].s1++;
return;
}
int mid=(l+r)/2;
build(d*2,l,mid,p);
build(d*2+1,mid+1,r,p);
updata(d);
}
int query(int d,int x,int y)
{
pushdown(d);
if (t[d].l==x&&t[d].r==y) return t[d].s0;
int mid=(t[d].l+t[d].r)/2;
if (y<=mid) return query(d*2,x,y);
else if (x>mid) return query(d*2+1,x,y);
else return query(d*2,x,mid)+query(d*2+1,mid+1,y);
}
void ins0(int d,int x,int y)
{
pushdown(d);
if (t[d].l==x&&t[d].r==y)
{
t[d].s1=0;
t[d].s0=t[d].r-t[d].l+1;
t[d].tag=0;
return;
}
int mid=(t[d].l+t[d].r)/2;
if (y<=mid) ins0(d*2,x,y);
else if (x>mid) ins0(d*2+1,x,y);
else
{
ins0(d*2,x,mid);
ins0(d*2+1,mid+1,y);
}
updata(d);
}
void ins1(int d,int x,int y)
{
pushdown(d);
if (t[d].l==x&&t[d].r==y)
{
t[d].s0=0;
t[d].s1=t[d].r-t[d].l+1;
t[d].tag=1;
return;
}
int mid=(t[d].l+t[d].r)/2;
if (y<=mid) ins1(d*2,x,y);
else if (x>mid) ins1(d*2+1,x,y);
else
{
ins1(d*2,x,mid);
ins1(d*2+1,mid+1,y);
}
updata(d);
}
int find(int d,int x)
{
if (t[d].l==t[d].r)
if (t[d].s0) return 0;
else return 1;
pushdown(d);
int mid=(t[d].l+t[d].r)/2;
if (x<=mid) return find(d*2,x);
else return find(d*2+1,x);
}
int main()
{
//freopen("4552.in","r",stdin);
//freopen("test.out","w",stdout);
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",&q[i].op,&q[i].l,&q[i].r);
int w;
scanf("%d",&w);
int l=1,r=n;
while (l<=r)
{
int mid=(l+r)/2;
build(1,1,n,mid);
for (int i=1;i<=m;i++)
{
int x=query(1,q[i].l,q[i].r),y=q[i].r-q[i].l+1-x;
if (q[i].op==0)
{
if (x) ins0(1,q[i].l,q[i].l+x-1);
if (q[i].l+x<=q[i].r) ins1(1,q[i].l+x,q[i].r);
}else
{
if (y) ins1(1,q[i].l,q[i].l+y-1);
if (q[i].l+y<=q[i].r) ins0(1,q[i].l+y,q[i].r);
}
}
if (find(1,w)==1) l=mid+1;
else r=mid-1;
}
printf("%d",l-1);
}