3130ソート
8201 ワード
Taskは1−nの全配列を与え,m回の操作は2種類に分けられる:①(0,l,r)区間[l,r]を昇順に②( 1,l,r)区間[l,r]を降順に配列する.n,m<=1e5
Solution 6秒の時限は、本当に暴力的な良いタイミングでsort関数sort(A+l,A+r+1,cmp)で区間[l,r]を昇順または降順に並べることができ、80分になります.しかし本人は下品で、sort(A+l+1,A+r+1)と書いてありますが、意外にも60分も普段のsortが(A,A+n)か(A+1,A+n+1)で、それぞれ左端点、右端点+1の位置だと思います.
「二分は一つの方向」二分の利点:知識を求める問題を判定問題に変換する.類似のテーマ:区間第k値、中位数.
二分xは、解がx以上であるか否かを判定する.xに従って、x以上の数を1とし、x未満の数を0とする.m回操作後、idビット上の数が1であれば実行可能と判定する.
問題は、1つの01シーケンス、m回の操作後、idビットの数が1であるかどうかに変換される.1区間が01しかないため,昇順降順にかかわらず0と1の境界点が1つある.区間の長さが一定であるため,区間の和を求めると,1の個数を見つけることができる.②境界線の前部分をc、後部分をc^1とする.(cは0または1)である.
区間加算、区間更新は、遅延更新のセグメントツリーで完了できます.
Solution 6秒の時限は、本当に暴力的な良いタイミングでsort関数sort(A+l,A+r+1,cmp)で区間[l,r]を昇順または降順に並べることができ、80分になります.しかし本人は下品で、sort(A+l+1,A+r+1)と書いてありますが、意外にも60分も普段のsortが(A,A+n)か(A+1,A+n+1)で、それぞれ左端点、右端点+1の位置だと思います.
「二分は一つの方向」二分の利点:知識を求める問題を判定問題に変換する.類似のテーマ:区間第k値、中位数.
二分xは、解がx以上であるか否かを判定する.xに従って、x以上の数を1とし、x未満の数を0とする.m回操作後、idビット上の数が1であれば実行可能と判定する.
問題は、1つの01シーケンス、m回の操作後、idビットの数が1であるかどうかに変換される.1区間が01しかないため,昇順降順にかかわらず0と1の境界点が1つある.区間の長さが一定であるため,区間の和を求めると,1の個数を見つけることができる.②境界線の前部分をc、後部分をc^1とする.(cは0または1)である.
区間加算、区間更新は、遅延更新のセグメントツリーで完了できます.
const int M=1e5+3;
int A[M];
int n,m,pos;
struct node1{
int cnt[2],l,r,f;
inline void clear(){
memset(cnt,0,sizeof(cnt));
}
}res;
struct node2{
int a,l,r;
}Q[M];
struct Segment_Tree{
node1 t[M<<2];
inline void up(int p){
rep(i,0,1)
t[p].cnt[i]=t[lsn(p)].cnt[i]+t[rsn(p)].cnt[i];
}
inline void down(int p){
if(t[p].f==-1)return;
int c=t[p].f,l=lsn(p),r=rsn(p);
t[l].f=t[r].f=c;
t[l].cnt[c]=t[l].r-t[l].l+1;
t[r].cnt[c]=t[r].r-t[r].l+1;
t[l].cnt[c^1]=t[r].cnt[c^1]=0;
t[p].f=-1;
}
inline void build(int l,int r,int x,int p){
t[p].l=l,t[p].r=r;t[p].f=-1;
if(l==r){
bool a=(A[l]>=x);
t[p].cnt[a]=1;t[p].cnt[a^1]=0;
return;
}
int mid=l+r>>1;
build(l,mid,x,lsn(p));
build(mid+1,r,x,rsn(p));
up(p);
}
inline void query(int L,int R,int l,int r,int p){
if(l==L&&r==R){
rep(i,0,1)res.cnt[i]+=t[p].cnt[i];
return;
}
down(p);
int mid=L+R>>1;
if(r<=mid)query(L,mid,l,r,lsn(p));
else if(l>mid)query(mid+1,R,l,r,rsn(p));
else{
query(L,mid,l,mid,lsn(p));
query(mid+1,R,mid+1,r,rsn(p));
}
}
inline void update(int L,int R,int l,int r,int c,int p){// c
if(l==L&&r==R){
t[p].cnt[c]=r-l+1;
t[p].cnt[c^1]=0;
t[p].f=c;
return;
}
down(p);
int mid=L+R>>1;
if(r<=mid)update(L,mid,l,r,c,lsn(p));
else if(l>mid)update(mid+1,R,l,r,c,rsn(p));
else{
update(L,mid,l,mid,c,lsn(p));
update(mid+1,R,mid+1,r,c,rsn(p));
}
up(p);
}
}T;
struct P100{
inline void input(){
rd(n);rd(m);
rep(i,1,n)rd(A[i]);
rep(i,1,m){
rd(Q[i].a);rd(Q[i].l);rd(Q[i].r);
}
rd(pos);
}
inline bool check(int x){// >=x
int a,l,r;
T.build(1,n,x,1);
rep(i,1,m){
res.clear();
a=Q[i].a,l=Q[i].l,r=Q[i].r;
T.query(1,n,l,r,1);
if(min(res.cnt[0],res.cnt[1])==0)continue;// 0 1
T.update(1,n,l,l+res.cnt[a]-1,a,1);// a
T.update(1,n,l+res.cnt[a],r,a^1,1);// a^1
}
res.clear();
T.query(1,n,pos,pos,1);
return res.cnt[1]==1;
}
inline void solve(){
input();
int l=1,r=n,mid,ans;
while(l<=r){
mid=l+r>>1;
if(check(mid)){l=mid+1;ans=mid;}
else r=mid-1;
}
sc(ans);
}
}P100;
int main(){
P100.solve();
return 0;
}