玲珑杯Round#20-E 1157 造物主的戒律 动态主席树算法
2017-09-08 21:03
417 查看
当初主要就是为了这里学的主席树。
之前博客已经讲了主席树,这里也相当于模板题,看了前面的讲解应该可以直接AC了。
静态主席树讲解
动态主席树讲解
学动态之前先学静态!!!
题目链接:http://www.ifrog.cc/acm/problem/1157
其实转换一下也是比较简单的,比如我们求l,r,x,k1,k2。
先求出区间[l,r]中<=x的数有cnt个,>x的数有tmp个(总数-cnt)。判断一下k1和cnt的大小,如果k1<=cnt就直接求区间[l,r]第k1小数即可否则就输出-1。然后判断k2和tmp的大小,如果k2<=tmp就转换成求区间[l,r]第cnt+k2小数否则输出-1即可。
所以最后查询依旧是按区间第k小查询,只是多加了个判断而已。
我的代码把所有的x也加入到序列再离散化,其实不必要(之后队友提醒后才知道)。我之前是想把x加进去后好找它的位置然后计算cnt,但其实就算不加也是可以直接找到的(TAT。。。)
之前博客已经讲了主席树,这里也相当于模板题,看了前面的讲解应该可以直接AC了。
静态主席树讲解
动态主席树讲解
学动态之前先学静态!!!
题目链接:http://www.ifrog.cc/acm/problem/1157
题意
中文题目就不说了,自己看。题解
这题唯一的变化就是加了一个<=x和>x的限制条件。其实转换一下也是比较简单的,比如我们求l,r,x,k1,k2。
先求出区间[l,r]中<=x的数有cnt个,>x的数有tmp个(总数-cnt)。判断一下k1和cnt的大小,如果k1<=cnt就直接求区间[l,r]第k1小数即可否则就输出-1。然后判断k2和tmp的大小,如果k2<=tmp就转换成求区间[l,r]第cnt+k2小数否则输出-1即可。
所以最后查询依旧是按区间第k小查询,只是多加了个判断而已。
我的代码把所有的x也加入到序列再离散化,其实不必要(之后队友提醒后才知道)。我之前是想把x加进去后好找它的位置然后计算cnt,但其实就算不加也是可以直接找到的(TAT。。。)
代码
#include <bits/stdc++.h> using namespace std; const int maxn = 8e5+5; const int maxm = 4e5+5; int T[maxn],L[maxn*20],R[maxn*20],sum[maxn*20]; int sz[maxm],h[maxn]; int tot,num; struct node{ int l,r,x,k1,k2; }Q[maxm]; void build(int& rt,int l,int r) { rt = ++tot; sum[rt] = 0; if(l==r) return; int mid = (l+r)>>1; build(L[rt],l,mid); build(R[rt],mid+1,r); } void update(int& rt,int pre,int x,int l,int r) { rt = ++tot; L[rt] = L[pre]; R[rt] = R[pre]; sum[rt] = sum[pre]+1; if(l==r) return; int mid = (l+r)>>1; if(x<=mid) update(L[rt],L[pre],x,l,mid); else update(R[rt],R[pre],x,mid+1,r); } int query(int s,int e,int l,int r,int k) { if(l==r) return l; int res = sum[L[e]]-sum[L[s]]; int mid = (l+r)>>1; if(k<=res) return query(L[s],L[e],l,mid,k); else query(R[s],R[e],mid+1,r,k-res); } int query_num(int x,int s,int e,int l,int r) { if(r<=x) return sum[e]-sum[s]; else if(x<l) return 0; else { int mid = (l+r)>>1; return query_num(x,L[s],L[e],l,mid)+query_num(x,R[s],R[e],mid+1,r); } } int main() { int n,m; num=tot=0; scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) scanf("%d",sz+i),h[++num]=sz[i]; for(int i=1;i<=m;i++) { scanf("%d%d%d%d%d",&Q[i].l,&Q[i].r,&Q[i].x,&Q[i].k1,&Q[i].k2); h[++num] = Q[i].x; } sort(h+1,h+1+num); int tmp = unique(h+1,h+1+num)-h-1; num = tmp; build(T[0],1,num); for(int i=1;i<=n;i++) update(T[i],T[i-1],lower_bound(h+1,h+1+num,sz[i])-h,1,num); int ans,cnt; for(int i=1;i<=m;i++) { cnt=query_num(lower_bound(h+1,h+1+num,Q[i].x)-h,T[Q[i].l-1],T[Q[i].r],1,num); printf("%d ",Q[i].k1<=cnt ? h[query(T[Q[i].l-1],T[Q[i].r],1,num,Q[i].k1)] : -1); int tmp = sum[T[Q[i].r]]-sum[T[Q[i].l-1]]-cnt; printf("%d\n",Q[i].k2<=tmp ? h[query(T[Q[i].l-1],T[Q[i].r],1,num,cnt+Q[i].k2)] : -1); } return 0; }
相关文章推荐
- 玲珑杯 1157 - 造物主的戒律 主席树+离散化
- “玲珑杯”ACM比赛 Round #20 E -- 造物主的戒律(主席树)
- linlong 1157 - 造物主的戒律(主席树)
- 玲珑杯#20 造物主的戒律
- 动态调度算法:记分牌算法&Tomasulo算法
- 嵌套模型(DAG上的动态规划)—动态规划入门(算法经典入门)
- 算法导论 第15章 动态规划:15.1钢条切割
- 5.极小极大化搜索与α-β剪枝:编程实现人机“三子棋”小游戏并对算法过程进行动态展示
- 【算法系列】——代码实践动态规划
- 算法实验之动态规划
- 要素动态跟踪的算法
- 【算法很难很重要】1.五大常用算法之动态规划
- 算法1.1 下压栈(LIFO)能动态调整数组的大小
- 算法学习之动态规划(leetcode 44 Wildcard Matching)
- 【数据结构与算法】动态查找--二叉排序树
- 自己实现的一个寻径算法的框架,具体算法采用动态库模式,可以非常方便灵活地尝试多种寻径算法
- 算法导论之平摊分析(动态表)
- C#写的有关汇编指令的动态调度算法的仿真程序
- 动态顺序表算法
- 短信内容分词(支持动态10~14位纯数字工作单号的签收信息,用在公司业务系统,很实用的算法)