题目:题目链接

题意:有编号从1到n的n个球和n个杯子. 每一个杯子里有一个球, 进行m次排序操作,每次操作给出l,r. 如果l<r,将[l,r]范围内的球按升序排序, 否则降序排, 问中间位置的数是多少.

思路:

  暴力复杂度为m*nlog(n), 不能暴力排序

  二分答案, 对于当前mid, 我们将大于等于mid的数记为1, 否则记0, 则排序就是将某个区间的数改为1或0, 通过线段树区间更新可以方便的做到, 对排序后的结果查询判断二分区间应该取左还是取右, 若中间的数是1, 则说明答案大于等于当前的数, l右移, 否则左移

AC代码:

 #include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
#include <string>
#include <map>
#include <set>
#include <unordered_map>
#include <unordered_set>
#include <queue>
#include <stack>
#include <list> #define FRER() freopen("in.txt", "r", stdin)
#define FREW() freopen("out.txt", "w", stdout) #define INF 0x3f3f3f3f
#define eps 1e-8 using namespace std; const int maxn = 1e5 + ; int a[maxn], ql[maxn], qr[maxn], tree[maxn << ], lazy[maxn << ]; void build(int l, int r, int rt, int num) {
lazy[rt] = ;
if(l == r) {
tree[rt] = (a[l] >= num);
return ;
}
int m = (l + r) >> ;
build(l, m, rt << , num);
build(m + , r, rt << |, num);
tree[rt] = tree[rt << ] + tree[rt << |];
} void pushdown(int l, int r, int rt) {
int m = (l + r) >> ;
lazy[rt << ] = lazy[rt << |] = lazy[rt];
if(lazy[rt] == ) {
tree[rt << |] = min(tree[rt], r - m);
tree[rt << ] = tree[rt] - tree[rt << |];
}
else if(lazy[rt] == ){
tree[rt << ] = min(tree[rt], m - l + );
tree[rt << |] = tree[rt] - tree[rt << ];
}
lazy[rt] = ;
} int querySum(int x, int y, int l, int r, int rt) {
if(x <= l && y >= r) return tree[rt];
if(lazy[rt]) pushdown(l, r, rt);
int m = (l + r) >> , sum = ;
if(x <= m) sum += querySum(x, y, l, m, rt << );
if(y > m) sum += querySum(x, y, m + , r, rt << |);
return sum;
} int query(int pos, int l, int r, int rt) {
if(l == r) return tree[rt];
if(lazy[rt]) pushdown(l, r, rt);
int m = (l + r) >> ;
if(pos <= m) return query(pos, l, m, rt << );
else return query(pos, m + , r, rt << |);
} void update(int x, int y, int l, int r, int rt, int flag, int sum) {
if(x <= l && y >= r) {
tree[rt] = sum;
lazy[rt] = flag;
return ;
}
if(lazy[rt]) pushdown(l, r, rt);
int m = (l + r) >> ;
if(y <= m) update(x, y, l, m, rt << , flag, sum);
else if(x > m) update(x, y, m + , r, rt << |, flag, sum);
else {
int lsum, rsum;
if(flag== ) {
rsum = min(sum, y - m);
lsum = sum - rsum;
}
else if(flag == ){
lsum = min(sum, m - x + );
rsum = sum - lsum;
}
update(x, m, l, m, rt << , flag, lsum);
update(m + , y, m + , r, rt << |, flag, rsum);
}
tree[rt] = tree[rt << ] + tree[rt << |];
} bool judge(int n, int m, int mid) {
build(, n, , mid);
for(int i = ; i < m; ++i) {
int sum = querySum(min(ql[i], qr[i]), max(ql[i], qr[i]), , n, );
if(ql[i] <= qr[i]) update(ql[i], qr[i], , n, , , sum);
else update(qr[i], ql[i], , n, , , sum);
}
return query(( + n) >> , , n, );
} int main()
{
//FRER();
ios::sync_with_stdio();
cin.tie(); int n, m;
cin >> n >> m;
for(int i = ; i <= n; ++i) cin >> a[i];
for(int i = ; i < m; ++i) cin >> ql[i] >> qr[i];
int l = , r = n, ans;
while(l <= r) {
int mid = (l + r) >> ;
if(judge(n, m, mid))
ans = mid, l = mid + ;
else r = mid - ;
}
cout << ans << endl;
return ;
}

Hacker Cups and Balls Gym - 101234A 二分+线段树的更多相关文章

  1. Codeforces Gym 100231B Intervals 线段树+二分+贪心

    Intervals 题目连接: http://codeforces.com/gym/100231/attachments Description 给你n个区间,告诉你每个区间内都有ci个数 然后你需要 ...

  2. J - Joseph and Tests Gym - 102020J (二分+线段树)

    题目链接:https://cn.vjudge.net/contest/283920#problem/J 题目大意:首先给你n个门的高度,然后q次询问,每一次询问包括两种操作,第一种操作是将当前的门的高 ...

  3. HDU4614 Vases and Flowers 二分+线段树

    分析:感觉一看就是二分+线段树,没啥好想的,唯一注意,当开始摆花时,注意和最多能放的比大小 #include<iostream> #include<cmath> #includ ...

  4. Educational Codeforces Round 61 D 二分 + 线段树

    https://codeforces.com/contest/1132/problem/D 二分 + 线段树(弃用结构体型线段树) 题意 有n台电脑,只有一个充电器,每台电脑一开始有a[i]电量,每秒 ...

  5. 【BZOJ-3110】K大数查询 整体二分 + 线段树

    3110: [Zjoi2013]K大数查询 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 6265  Solved: 2060[Submit][Sta ...

  6. hdu6070 Dirt Ratio 二分+线段树

    /** 题目:hdu6070 Dirt Ratio 链接:http://acm.hdu.edu.cn/showproblem.php?pid=6070 题意:给定n个数,求1.0*x/y最小是多少.x ...

  7. K-th occurrence HDU - 6704 (后缀数组+二分线段树+主席树)

    大意: 给定串s, q个询问(l,r,k), 求子串s[l,r]的第kk次出现位置. 这是一篇很好的题解: https://blog.csdn.net/sdauguanweihong/article/ ...

  8. 2016-2017 National Taiwan University World Final Team Selection Contest A - Hacker Cups and Balls

    题目: Dreamoon likes algorithm competitions very much. But when he feels crazy because he cannot figur ...

  9. 【Codeforces】Gym 101608G WiFi Password 二分+线段树

    题意 给定$n$个数,求有最长的区间长度使得区间内数的按位或小于等于给定$v$ 二分区间长度,线段树处理出区间或,对每一位区间判断 时间复杂度$O(n\log n \log n)$ 代码 #inclu ...

随机推荐

  1. css3之移动平台资源

    随着移动端越来越普及,前端技术也是百花齐放,但目前移动平台的技术已经趋向于成熟,记得刚实习的时候就是接触的移动端,但现在2年多来,期间遇到了很多莫名其妙的问题,见证了手机用户量的突飞猛进,兴喜的是更多 ...

  2. jquery的html()、text()、val()的区别和用法

    1.html() html()[无参]的使用方法是获取某元素内部的HTML代码,包括各种标签: 例:句1:<p>不知道大家高考的理综试卷里有没有关于科学家及其成就的选择题</p> ...

  3. $.ajax显示进度条

  4. Android Recyclerview隐藏item的所在区域显示大空白问题的解决方案

    最近搞了下Recyclerview,做了增加.删除item的功能.item上方有卡签 插个图片看下效果,点击底下的添加上去,同时,底下的item消失,这个用notifyItemInserted和not ...

  5. centos7按报错dracut

    在Windows下,将从CentOS官网上下载的CentOS7镜像文件,用UltrISO以硬盘镜像方法写入U盘 安装过程中出现下面错误: dracut-initqueue[624]:Warning: ...

  6. Java -GUI开发九九乘法表

    Java GUI开发九九乘法表 (1)实现目标: 利用java自带的awt包,基础控件开发一个九九乘法表,点击可以显示对应的乘法口诀. (2)控件选择: 点击——Button 显示——TextFiel ...

  7. windows10家庭中文版升级专业版或企业版简单方便的操作方法

    以管理员的身份运行cmd 1 ,升级到专业版输入:slmgr /ipk W269N-WFGWX-YVC9B-4J6C9-T83GX 输入slmgr.vbs -skms zh.us.to 激活 2, 升 ...

  8. 来自SaberSama的HTML总结

    html 为什么要转过来呢? 因为我觉到,同样是一个初学者,应该互相学习,交流. html:是Hyper Text Markup Language的简写,即超文本标记语言. 网页的组成成分为HTML- ...

  9. 如何更换vim-airline的theme

    仓库位置: 点我直达 (主题以前是和airline在同个仓库的,现在独立出来了) 这些内置的这些主题,可以直接使用,方法是在 “.vimrc”文件中写 let g:airline_theme=&quo ...

  10. 笨办法学Python(三十一)

    习题 31: 作出决定 这本书的上半部分你打印了一些东西,而且调用了函数,不过一切都是直线式进行的.你的脚本从最上面一行开始,一路运行到结束,但其中并没有决定程序流向的分支点.现在你已经学了 if,  ...