博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
2019牛客暑期多校训练营(第七场)- Find the median
阅读量:4951 次
发布时间:2019-06-11

本文共 3533 字,大约阅读时间需要 11 分钟。

线段树

显然的方法是把区间离散化以后,维护每个区间内出现的数的个数。

查询的时候直接用左端点的值加上查询的数的排名/区间插入的次数就行了。

处理这类问题一般是让每个端点的右区间+1,然后用叶子节点来保存一段区间的信息。

当我们的线段树递归到叶子结点的时候,l = r, 我们如果让线段树维护当前区间每个数出现的次数,叶子节点显然不好处理,因为l = r。

所以我们可以让每个区间维护的信息往后扩展一点。

假设当前区间为[l...r], 这里l和r均为离散化以后的值。此时可以让线段树维护[l..r+1)区间内每个数出现的次数,这样到了叶子节点实际上是[l, l+1)区间内每个数出现的次数,(此时l=r)。

这样问题就简化完成了。

在修改的时候也要让右端点-1,这样才符合我们对维护的信息的定义.

#include 
#define INF 0x3f3f3f3f#define full(a, b) memset(a, b, sizeof a)#define __fastIn ios::sync_with_stdio(false), cin.tie(0)#define range(x) (x).begin(), (x).end()#define pb push_backusing namespace std;typedef long long LL;inline int lowbit(int x){ return x & (-x); }inline int read(){ int ret = 0, w = 0; char ch = 0; while(!isdigit(ch)){ w |= ch == '-', ch = getchar(); } while(isdigit(ch)){ ret = (ret << 3) + (ret << 1) + (ch ^ 48); ch = getchar(); } return w ? -ret : ret;}template
inline A __lcm(A a, A b){ return a / __gcd(a, b) * b; }template
inline A fpow(A x, B p, C lyd){ A ans = 1; for(; p; p >>= 1, x = 1LL * x * x % lyd)if(p & 1)ans = 1LL * x * ans % lyd; return ans;}const int N = 400005;int n, x[N], y[N], L[N], R[N], a1, b1, c1, a2, b2, c2, m1, m2, b[N<<1], tot;int lazy[N<<3];LL freq[N<<3]; void add(int rt, int l, int r, int val){ lazy[rt] += val; freq[rt] += 1LL * (b[r + 1] - b[l]) * val;} void push_down(int rt, int l, int r, int val){ int mid = (l + r) >> 1; add(rt << 1, l, mid, val); add(rt << 1 | 1, mid + 1, r, val); lazy[rt] = 0;} void push_up(int rt){ freq[rt] = freq[rt << 1] + freq[rt << 1 | 1];} void buildTree(int rt, int l, int r){ if(l == r){ freq[rt] = lazy[rt] = 0; return; } int mid = (l + r) >> 1; buildTree(rt << 1, l, mid); buildTree(rt << 1 | 1, mid + 1, r); push_up(rt);} void insert(int rt, int l, int r, int il, int ir){ if(l == il && r == ir){ add(rt, l, r, 1); return; } push_down(rt, l, r, lazy[rt]); int mid = (l + r) >> 1; if(ir <= mid) insert(rt << 1, l, mid, il, ir); else if(il > mid) insert(rt << 1 | 1, mid + 1, r, il, ir); else insert(rt << 1, l, mid, il, mid), insert(rt << 1 | 1, mid + 1, r, mid + 1, ir); push_up(rt);} int query(int rt, int l, int r, LL k){ if(l > r) return 0; if(l == r){ return b[l] + (k - 1) / lazy[rt]; } push_down(rt, l, r, lazy[rt]); int mid = (l + r) >> 1; if(freq[rt << 1] >= k) return query(rt << 1, l, mid, k); return query(rt << 1 | 1, mid + 1, r, k - freq[rt << 1]);} int main(){ scanf("%d", &n); scanf("%d%d%d%d%d%d", &x[1], &x[2], &a1, &b1, &c1, &m1); scanf("%d%d%d%d%d%d", &y[1], &y[2], &a2, &b2, &c2, &m2); for(int i = 3; i <= n; i ++){ x[i] = (1LL * a1 * x[i - 1] + 1LL * b1 * x[i - 2] + c1) % m1; y[i] = (1LL * a2 * y[i - 1] + 1LL * b2 * y[i - 2] + c2) % m2; } for(int i = 1; i <= n; i ++){ L[i] = min(x[i], y[i]) + 1; R[i] = max(x[i], y[i]) + 1; R[i] ++, b[++tot] = L[i], b[++tot] = R[i]; } sort(b + 1, b + tot + 1); tot = (int)(unique(b + 1, b + tot + 1) - b - 1);// b[tot + 1] = b[tot] + 1;// tot ++; LL sum = 0; buildTree(1, 1, tot); for(int i = 1; i <= n; i ++){ sum += R[i] - L[i]; L[i] = (int)(lower_bound(b + 1, b + tot + 1, L[i]) - b); R[i] = (int)(lower_bound(b + 1, b + tot + 1, R[i]) - b); insert(1, 1, tot, L[i], R[i] - 1); printf("%d\n", query(1, 1, tot, (sum + 1) / 2)); } return 0;}

转载于:https://www.cnblogs.com/onionQAQ/p/11328190.html

你可能感兴趣的文章
Codeforces Round #384 (Div. 2) D. Chloe and pleasant prizes(树形DP)
查看>>
flex布局中flex-basis的理解
查看>>
93. Restore IP Addresses
查看>>
46. Permutations
查看>>
找出点的密集区域,javascript实现,html5 canvas效果图
查看>>
Microsoft project 快捷键
查看>>
hadoop之定制自己的sort过程
查看>>
DataTable和 DataRow的 区别与联系
查看>>
字符串和编码的问题
查看>>
检索COM 类工厂中CLSID 为 {00024500-0000-0000-C000-000000000046}的组件时失败
查看>>
mysql数据库中数据类型
查看>>
python-实现生产者消费者模型
查看>>
APP网络优化篇
查看>>
算法18-----判断是否存在符合条件的元素【list】
查看>>
《刑法》关于拐卖妇女儿童犯罪的规定
查看>>
Windows的本地时间(LocalTime)、系统时间(SystemTime)、格林威治时间(UTC-Time)、文件时间(FileTime)之间的转换...
查看>>
alias重启后失效了
查看>>
RestTemplate的Object与Entity的区别
查看>>
Fireworks基本使用
查看>>
《代码整洁之道》学习记录
查看>>