1. 程式人生 > >bzoj 4552 [Tjoi2016&Heoi2016]排序 (二分答案 線段樹)

bzoj 4552 [Tjoi2016&Heoi2016]排序 (二分答案 線段樹)

print %d 線段樹 https 代碼 數組 pda lse 線段

題目鏈接:https://www.lydsy.com/JudgeOnline/problem.php?id=4552

題意:

給你一個1-n的全排列,m次操作,操作由兩種:1.將[l,r]升序排序,2.將[l,r]降序排列

最後給你一個點p,輸出這個點的數

思路:

因為這道題只有一個詢問,只需要知道一個位置的值,且序列是全排列,那麽我們可以對答案進行二分,首先我們先選定一個值x,將數組中比x大的全部變成1,小於等於x的變為0,然後用線段樹去模擬排序的操作,最後我們需要查詢p位置的數如果為1那麽代表答案大於當前數x,為0代表答案小於當前數x,繼續二分就好了

實現代碼:

#include<bits/stdc++.h>
using
namespace std; #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define mid int m = (l + r) >> 1 const int M = 1e5 +10; int sum[M<<2],flag[M<<2],lazy[M<<2],a[M],b[M],op[M]; struct node{ int l,r; }q[M]; void pushup(int rt){ sum[rt] = sum[rt<<1
] + sum[rt<<1|1]; } void pushdown(int l,int r,int rt){ if(flag[rt]){ mid; sum[rt<<1] = lazy[rt]*(m-l+1); sum[rt<<1|1] = lazy[rt]*(r-m); lazy[rt<<1] = lazy[rt<<1|1] = lazy[rt]; flag[rt<<1] = flag[rt<<1|1] = flag[rt]; flag[rt]
= 0; } } void build(int l,int r,int rt){ flag[rt] = 0; lazy[rt] = 0; if(l == r){ sum[rt] = b[l]; return; } mid; build(lson); build(rson); pushup(rt); } void update(int L,int R,int c,int l,int r,int rt){ if(L <= l&&R >= r){ sum[rt] = c*(r-l+1); lazy[rt] = c; flag[rt] = 1; return ; } pushdown(l,r,rt); mid; if(L <= m) update(L,R,c,lson); if(R > m) update(L,R,c,rson); pushup(rt); } int query(int L,int R,int l,int r,int rt){ if(L <= l&&R >= r){ return sum[rt]; } pushdown(l,r,rt); mid; int ret = 0; if(L <= m) ret += query(L,R,lson); if(R > m) ret += query(L,R,rson); return ret ; } int main() { int n,k,pos; scanf("%d%d",&n,&k); for(int i = 1;i <= n;i ++) scanf("%d",&a[i]); for(int i = 1;i <= k;i ++) scanf("%d%d%d",&op[i],&q[i].l,&q[i].r); scanf("%d",&pos); int l = 1,r = n; while(l < r){ mid; for(int i = 1;i <= n;i ++){ if(a[i] > m) b[i] = 1; else b[i] = 0; } build(1,n,1); for(int i = 1;i <= k;i ++){ int cnt = query(q[i].l,q[i].r,1,n,1); if(op[i]){ //降序排列,1放在前面,0放在後面 if(cnt) update(q[i].l,q[i].l+cnt-1,1,1,n,1); if(cnt+q[i].l <= q[i].r) update(q[i].l+cnt,q[i].r,0,1,n,1); } else{ //升序排序,1放在後面,0放在前面 if(cnt) update(q[i].r-cnt+1,q[i].r,1,1,n,1); if(q[i].r-cnt >= q[i].l) update(q[i].l,q[i].r-cnt,0,1,n,1); } } if(query(pos,pos,1,n,1)) l = m+1; else r = m; } printf("%d\n",l); return 0; }

bzoj 4552 [Tjoi2016&Heoi2016]排序 (二分答案 線段樹)