Hacker Cups and Balls Gym - 101234A 二分+线段树
题目:题目链接
题意:有编号从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 二分+线段树的更多相关文章
- Codeforces Gym 100231B Intervals 线段树+二分+贪心
Intervals 题目连接: http://codeforces.com/gym/100231/attachments Description 给你n个区间,告诉你每个区间内都有ci个数 然后你需要 ...
- J - Joseph and Tests Gym - 102020J (二分+线段树)
题目链接:https://cn.vjudge.net/contest/283920#problem/J 题目大意:首先给你n个门的高度,然后q次询问,每一次询问包括两种操作,第一种操作是将当前的门的高 ...
- HDU4614 Vases and Flowers 二分+线段树
分析:感觉一看就是二分+线段树,没啥好想的,唯一注意,当开始摆花时,注意和最多能放的比大小 #include<iostream> #include<cmath> #includ ...
- Educational Codeforces Round 61 D 二分 + 线段树
https://codeforces.com/contest/1132/problem/D 二分 + 线段树(弃用结构体型线段树) 题意 有n台电脑,只有一个充电器,每台电脑一开始有a[i]电量,每秒 ...
- 【BZOJ-3110】K大数查询 整体二分 + 线段树
3110: [Zjoi2013]K大数查询 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 6265 Solved: 2060[Submit][Sta ...
- hdu6070 Dirt Ratio 二分+线段树
/** 题目:hdu6070 Dirt Ratio 链接:http://acm.hdu.edu.cn/showproblem.php?pid=6070 题意:给定n个数,求1.0*x/y最小是多少.x ...
- K-th occurrence HDU - 6704 (后缀数组+二分线段树+主席树)
大意: 给定串s, q个询问(l,r,k), 求子串s[l,r]的第kk次出现位置. 这是一篇很好的题解: https://blog.csdn.net/sdauguanweihong/article/ ...
- 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 ...
- 【Codeforces】Gym 101608G WiFi Password 二分+线段树
题意 给定$n$个数,求有最长的区间长度使得区间内数的按位或小于等于给定$v$ 二分区间长度,线段树处理出区间或,对每一位区间判断 时间复杂度$O(n\log n \log n)$ 代码 #inclu ...
随机推荐
- Sass基础(二)
五.嵌套 在Sass中,嵌套有三种方式:选择器嵌套.属性嵌套.伪类嵌套 1.选择器嵌套 2.属性嵌套 3.伪类嵌套 六.混合宏 当样式变得越来越复杂,需要重复使用大段的样式时,使用变量就无法达到目的了 ...
- 1.字符串池化(intern)机制及拓展学习
1.字符串intern机制 用了这么久的python,时刻和字符串打交道,直到遇到下面的情况: a = "hello" b = "hello" print(a ...
- Vue.js - Day2
品牌管理案例 添加新品牌 删除品牌 根据条件筛选品牌 1.x 版本中的filterBy指令,在2.x中已经被废除: filterBy - 指令 <tr v-for="item in ...
- oracle的数值数据类型和兼容细分类型
Oracle存储数值类型的数据不区分int .double .float 等类型,统一使用number(p,s)来存储. 基本类型为 NUMBER(P,S) P范围1到38 S 范围 -84 到 12 ...
- 3.tomcat
1.进入网站http://www.apache.org 2.选择 3.关闭防火墙才可以让别人访问自己
- github设置添加SSH(转载自:破男孩)
注:本文来源于 破男孩 博客(http://www.cnblogs.com/ayseeing/p/3572582.html)能切实解决问题. 很多朋友在用github管理项目的时候,都是直接使用htt ...
- framework7对日历的一些效果处理
现在的要求是日历中要区分已打卡和未打卡的显示,并且当月只显示当月的日历状态,其他月份不显示状态,并且打卡的日期不能大于当日 实现代码(精确到天): HTML: <div class=" ...
- 2017.10.28 针对Java Web应用中错误异常处理方法的运用
针对Java Web应用中错误异常处理方法的运用 在javaweb中其异常都需要对Checked Exception之下的Exception进行继承,并且有选择地对发生的错误和异常进行处理.Java同 ...
- kubernetes-控制器statefulset和Job(十三)
从前面的学习我们知道使用Deployment创建的pod是无状态的,当挂载了Volume之后,如果该pod挂了,Replication Controller会再启动一个pod来保证可用性,但是由 ...
- 2.1-Java语言基础(keyword)
2.1 keyword watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvbXNpcmVuZQ==/font/5a6L5L2T/fontsize/400/fi ...