n個數的排列,兩種操作,一種將[l,r]區間內的數遞減排序,另一種將[l,r]中的數遞增排序,問最後第k個位置的數字是多少。
好題。
因為最後考慮的只是第k個位置的數字,二分答案。
每次將序列中比x大的都標記為1,其餘包括x標記為0,每次排序前,先查詢區間中有多少個1和0,然後按照操作將1和0分別更新到區間的左右兩部分,用線段樹區間更新區間查詢即可。判斷時如果第k個位置為0則r=m-1,否則l=m+1。
#include
using
namespace
std;
#define lson l, m, rt << 1
#define rson m + 1, r, rt << 1 | 1
const
int maxn = 1e5 + 10;
int n, q, k;
int a[maxn], b[maxn], op[maxn], ll[maxn], rr[maxn];
int c[maxn << 2], lazy[maxn << 2];
void pushup(int rt)
void pushdown(int rt, int len)
}void build(int l, int r, int rt)
int m = (l + r) >> 1;
build(lson);
build(rson);
pushup(rt);
}void update(int l, int r, int v, int l, int r, int rt)
pushdown(rt, r - l + 1);
int m = (l + r) >> 1;
if (l <= m) update(l, r, v, lson);
if (r > m) update(l, r, v, rson);
pushup(rt);
}int query(int l, int r, int l, int r, int rt)
int cal(int x)
build(1, n, 1);
//cout << c[1] << endl;
for (int i = 1; i <= q; i++)
else
}return (query(k, k, 1, n, 1) == 0);
}void solve(int l, int r)
else l = mid + 1;
}printf("%d\n", res);
}int main()
for (int i = 1; i <= q; i++)
scanf("%d%d%d", &op[i], &ll[i], &rr[i]);
scanf("%d", &k);
solve(1, n);
}return
0;}
HDU 5649 二分 線段樹
題意 給出乙個排列,每次操作 l,r 區間的數原地公升序或者降序,詢問最後k下標的數。二分最後的結果mid,然後把比mid大的換成1,小於等於mid的換成0,那麼公升序降序相當於求出區間中0的個數然後把前半段和後半段分別用0 1覆蓋。這樣只需要維護乙個區間查詢,區間修改的線段樹即可。include ...
hdu 4339 線段樹 二分
題意是給你兩個字串 進行兩種操作 1 修改其中乙個字串裡的某個字元2 詢問從i起兩個字串最多由多少個是相同的 先說一下做之前的想法 我是看別人介紹樹狀陣列是看到這道題的 本也想用樹狀陣列做 沒想上去 然後就改為線段樹了 有很明顯的點更新,區間查詢,所以選擇線段樹 思路 每個節點num 存3個值 p1...
hdu 4614 線段樹 二分
這題感覺有點坑,陣列越界了,看來以後陣列要盡可能的開大一些了。include include include include include using namespace std define maxn 60005 struct ee tree maxn 4 int n,m void build ...