[Hackerrank题目选做] Sorted Subsegments 二分+线段树
来源:互联网 发布:淘宝产品摄影moxin020 编辑:程序博客网 时间:2024/05/16 06:52
题目链接:https://www.hackerrank.com/challenges/sorted-subsegments
题目大意:给定n,q,k和一个大小为n的数组A,共有q组操作,每组操作给定l,r,要求将A[l]...A[r]按照升序排序,q组操作后求A[k]的值。(n,q<=7.5*10^4)
Part 1 骗分
菜鸡并不会这样的神题水题,只能按照万年不变的骗分策略去小数据暴力,大数据贪心,
可是-------满分80pts,就这样一个400B的代码骗了43.87pts!(骗分的力量是无穷的,滑稽.jpg)
#include <bits/stdc++.h>using namespace std;int a[75005],n,q,k,i,l,r;int main (){scanf ("%d%d%d",&n,&q,&k);for (i=0;i<n;i++){scanf ("%d",&a[i]);}int ll,rr;l=0;r=0; for (i=0;i<q;i++){ll=l;rr=r;scanf ("%d%d",&l,&r);if (!(l>=ll&&r<=rr)) {sort(a+l,a+r+1);}if ((double)(clock())/CLOCKS_PER_SEC>1.8){sort(a,a+n);break;} }printf ("%d",a[k]);return 0;}
Part 2 标算
然后,失去了思考能力的菜鸡博主打开了editorial,再次被教做人.
题解: 设bi为q次操作后形成的数组,ci为01数组,对于常数x,ci=(bi>=x).
然后考虑二分答案x,这样x就成为了一个不变量,
对于每次操作[l,r],考虑操作后对于c数组的影响,
首先,因为该区间内的数字不变,所以0,1的数量不变,
而且,一个显然的性质是-----一次操作后,0全部移到了左边,1全部移到了右边(因为数组变得有序化了),
这样,通过线段树维护序列c,通过判断ck是否为1进行二分,从而O(nlognlog(Maxn-Minn))时间内完成对a[k]的计算。
大体思想:若要维护具体数值,很难从O(n^2logn)的暴力做法中取得突破,
所以考虑用1个log的代价化具体数值为01变量,维护01数组表示大小关系从而做到更优秀的复杂度。
AC_Code: (这题可能需要卡常TAT)
#include <bits/stdc++.h>#define inf 1000000000#define ls pos<<1#define rs pos<<1|1using namespace std;struct node{int l,r,siz,tag,p;}t[300005];int a[75005],l[75005],r[75005],c[75005];int n,q,k;void build(int pos,int l,int r){t[pos].l=l,t[pos].r=r,t[pos].tag=0,t[pos].siz=r-l+1;if (l==r) {t[pos].p=c[l];return;}int mid=(l+r)>>1;build(ls,l,mid),build(rs,mid+1,r);t[pos].p=t[ls].p+t[rs].p;}inline void tag_down(int pos){if (t[pos].tag!=0){t[ls].tag=t[rs].tag=t[pos].tag;if (t[pos].tag==-1){t[ls].p=t[rs].p=0;}else{t[ls].p=t[ls].siz,t[rs].p=t[rs].siz;}t[pos].tag=0;}}int qr(int pos,int l,int r){if (t[pos].l==l&&t[pos].r==r) {return t[pos].p;}tag_down(pos);int mid=(t[pos].l+t[pos].r)>>1;if (r<=mid) return qr(ls,l,r);if (l>=mid+1) return qr(rs,l,r);return qr(ls,l,mid)+qr(rs,mid+1,r);}void modify(int pos,int l,int r,int d){if (t[pos].l==l&&t[pos].r==r){if (!d) {t[pos].p=0,t[pos].tag=-1;}else {t[pos].p=t[pos].siz,t[pos].tag=1;}return;}tag_down(pos);int mid=(t[pos].l+t[pos].r)>>1;if (r<=mid){modify(ls,l,r,d);}else{if (l>=mid+1) {modify(rs,l,r,d);}else {modify(ls,l,mid,d),modify(rs,mid+1,r,d);}}t[pos].p=t[ls].p+t[rs].p;}int main (){int i,j;int minn=inf,maxn=-inf;scanf ("%d%d%d",&n,&q,&k);for (i=1;i<=n;i++){scanf ("%d",&a[i]);if (a[i]<minn) {minn=a[i];}if (a[i]>maxn) {maxn=a[i];}}k++;for (i=1;i<=q;i++){scanf ("%d%d",&l[i],&r[i]);l[i]++,r[i]++;}int lc=minn,rc=maxn;while (lc<=rc){int mid=(lc+rc)>>1;for (i=1;i<=n;i++){if (a[i]>=mid) {c[i]=1;}else {c[i]=0;}}build(1,1,n);for (i=1;i<=q;i++){int num=qr(1,l[i],r[i]);if (l[i]<=r[i]-num) {modify(1,l[i],r[i]-num,0);}if (num>0) {modify(1,r[i]-num+1,r[i],1);}}int t=qr(1,k,k);if (t) {lc=mid+1;}else {rc=mid-1;}}printf ("%d\n",rc);return 0;}
阅读全文
0 0
- [Hackerrank题目选做] Sorted Subsegments 二分+线段树
- [Hackerrank题目选做] 出租车司机问题 数据结构+树分治
- [Hackerrank题目选做] Random Number Generator 二分+数学+猜结论
- [Hackerrank题目选做] Team Formation 贪心
- [Hackerrank题目选做] Tree Pruning
- [Hackerrank题目选做] Jim And Challenges
- Codeforecs 69E. Subsegments STL/线段树
- [Hackerrank题目选做] Kundu and Tree 组合数学
- [Hackerrank题目选做] Mathematical Expectation伪题解
- Hackerrank - Similar Pair 与线段树解法
- Poj3667 ( 线段树题目,不过用Splay做的 )
- 【hackerrank】字符串题目
- hdu3564(二分+线段树)
- hdu4614 二分+线段树
- hdu5217Brackets【线段树,二分】
- 【HDU4614】【线段树】【二分】
- HDU4791(线段树+二分)
- HDU5592(线段树+二分)
- 自己早期写的一个简单上下班打卡统计工时的考勤系统【整理版】
- Mybatis Plugin 破解
- android Service的用法
- 网站优化的3个seo小技巧
- llinux系统查询端口是否被占用
- [Hackerrank题目选做] Sorted Subsegments 二分+线段树
- 特长生模拟——八数码问题
- PCA 主成分分析Principal components analysis
- SDK安装的闪退问题
- 最新盘点当今10个顶尖的机床系统及厂家
- CTF 题目练习题库
- 哲学家就餐问题实现
- ubuntu 16.04 下配置intel/caffe
- [bzoj4931][SDOI省队集训2017]塔