HDU5649 DZY Loves Sorting 二分+线段树
2016-03-22 22:29
351 查看
上周六BC的最后一道题
感觉还是挺经典的做法的,首先因为是n的全排列,所以可以直接二分答案然后用线段树判断,好吧其实bc的题解说的已经很清楚了
这是一道良心的基础数据结构题。
我们二分a[k]a[k]的值,假设当前是midmid,然后把大于midmid的数字标为11,不大于midmid的数字标为00。然后对所有操作做完以后检查一下a[k]a[k]位置上是00还是11。
因为只有两种值,所以操作还是不难做的。只要用一个线段树,支持区间求和、区间赋值即可。这样要排序一个区间时只要查询一下里面有几个11和几个00,然后把前半段赋值为00,后半段赋值为11即可(降序的话就是反过来)。
复杂度是O(m\log ^2 n)O(mlog2n)的。
感觉还是挺经典的做法的,首先因为是n的全排列,所以可以直接二分答案然后用线段树判断,好吧其实bc的题解说的已经很清楚了
这是一道良心的基础数据结构题。
我们二分a[k]a[k]的值,假设当前是midmid,然后把大于midmid的数字标为11,不大于midmid的数字标为00。然后对所有操作做完以后检查一下a[k]a[k]位置上是00还是11。
因为只有两种值,所以操作还是不难做的。只要用一个线段树,支持区间求和、区间赋值即可。这样要排序一个区间时只要查询一下里面有几个11和几个00,然后把前半段赋值为00,后半段赋值为11即可(降序的话就是反过来)。
复杂度是O(m\log ^2 n)O(mlog2n)的。
#include <iostream> #include <cstring> #include <cstdio> #include <algorithm> #define maxn 100009 #define rep(i, j, k) for(int i = j; i <= k; i++) using namespace std; int n, m, k, f[maxn], tot[6 * maxn], all[maxn * 6]; int a[maxn], b[maxn], c[maxn], Ans; void insert (int x, int lx, int rx, int position, int num) { if (position > rx || position < lx) return; if (lx == rx && lx == position) { tot[x] = num; return; } int mid = (lx + rx) >> 1; if (position <= mid) insert (2 * x, lx, mid, position, num); else insert (2 * x + 1, mid + 1, rx, position, num); tot[x] = tot[2 * x] + tot[2 * x + 1]; return; } void set (int x, int la, int ra, int L, int R, int num) { if (R < L) return; if (L > ra || R < la) return; if (L <= la && ra <= R) { all[x] = num; tot[x] = num * (ra - la + 1); return; } int mid = (la + ra) >> 1; if (all[x] != -1) { all [2 * x] = all [2 * x + 1] = all [x], tot[x] = all[x] * (ra - la + 1); tot[2 * x] = all[x] * (mid - la + 1); tot[2 * x + 1] = all[x] * (ra - mid); all [x] = -1; } set (2 * x, la, mid, L, R, num); set (2 * x + 1, mid + 1, ra, L, R, num); tot[x] = tot[2 * x] + tot[2 * x + 1]; return; } int ask (int x, int la, int ra, int L, int R) { if (L > ra || R < la) return 0; if (L <= la && ra <= R) { if (all[x] != -1) tot[x] = all[x] * (ra - la + 1), all[x] = -1; return tot[x]; } int mid = (la + ra) >> 1; if (all[x] != -1) { all[2 * x] = all[2 * x + 1] = all[x]; tot[2 * x] = all[x] * (mid - la + 1); tot[2 * x + 1] = all[x] * (ra - mid); all[x] = -1; } int num = ask (2 * x, la, mid, L, R) + ask (2 * x + 1, mid + 1, ra, L, R); tot[x] = tot[2 * x] + tot[2 * x + 1]; return num; } void work () { int l = 1, r = n; while (l <= r) { memset (all, -1, sizeof (all)); memset (tot, 0, sizeof (tot)); int mid = (l + r) >> 1; rep (i, 1, n) insert (1, 1, n, i, f[i] >= mid ? 1 : 0); rep (i, 1, m) { int now = ask (1, 1, n, b[i], c[i]);//the num of 1 int other = c[i] - b[i] + 1 - now;//the num of 0 if (a[i] == 0) { set (1, 1, n, b[i], b[i] + other - 1, 0); set (1, 1, n, b[i] + other, c[i], 1); } else { set (1, 1, n, b[i], b[i] + now - 1, 1); set (1, 1, n, b[i] + now, c[i], 0); } } if (ask (1, 1, n, k, k) > 0) l = mid + 1, Ans = mid; else r = mid - 1; } printf ("%d\n", Ans); return ; } int main() { int Case; scanf("%d", &Case); while (Case--) { scanf ("%d%d", &n, &m); rep (i, 1, n) scanf ("%d", &f[i]); rep (i, 1, m) scanf ("%d%d%d", &a[i], &b[i], &c[i]); scanf ("%d", &k); work (); } return 0; }
相关文章推荐
- Win7下安装Node + WebMatrix
- 应用多级缓存模式支撑海量读服务
- Java day08 异常(2)
- swift 与oc 混编
- android颜色指列表
- kaungbin_DP S (POJ 3666) Making the Grade
- 疲备
- android中RecyclerView使用自定义的列表布局
- FZU 1911 Construct a Matrix(矩阵快速幂+找规律)
- 高精度问题--n的阶乘
- AC自动机
- Linux C 网络编程——多线程的聊天室实现(服务器端)
- 链表,折磨人的数据结构
- POJ 3666 Making the Grade
- tkinter 表格
- 复利计算器3.1
- Android——加载模式
- codeforces_612A. The Text Splitting
- msado15.tlh(407) : warning C4146: unary minus operator applied to unsigned type, result still unsign
- Linux中的权限表示---字母表示和数字表示