题目:题目链接

题意:有编号从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. 《C#多线程编程实现方式》

    一.使用线程的理由 1.可以使用线程将代码同其他代码隔离,提高应用程序的可靠性. 2.可以使用线程来简化编码. 3.可以使用线程来实现并发执行. 二.基本知识 1.进程与线程:进程作为操作系统执行程序 ...

  2. Angular JS + Express JS入门搭建网站

    3月份开始,接到了新的任务,跟UI开发有关,用的是Angular JS,Express JS等技术.于是周末顺便学习下新技术. 组里产品UI架构如下: 其中前端,主要使用Angular JS框架,另外 ...

  3. 浩顺晶密K-5 打卡时间设置

    公司有一台浩顺晶密K-5打卡设备,因为时间异常需要重新调整,设备外部就几个按钮,全部按了一遍发现没有任何变化,所以肯定是哪里操作不对,然后用钥匙打开这个设置,上面有一排文字,分别是设置.+.-.确认等 ...

  4. mongdb增加字段和删除字段

    增加字段 db.xxx.update({},{"$set":{"column1":1,"column2":0}},false,true); ...

  5. word禁止自动编号

    在回车.换行时使用 shift + enter

  6. April 19 2017 Week 16 Wednesday

    What would life be if we had no courage to attempt anything? 如果我们都没有勇气去尝试点什么,生活会变成什么样子呢? I remembere ...

  7. Centos下Yum安装PHP5.5,5.6

    默认的版本太低了,手动安装有一些麻烦,想采用Yum安装的可以使用下面的方案: 1.检查当前安装的PHP包 yum list installed | grep php 如果有安装的PHP包,先删除他们 ...

  8. 线程 task 使用三种方法

    1:用TaskFactory的实例: 运行结果为: 2. 使用task类的Factory属性 3.使用task类的实例,用start来启动任务.  当我们用Task类时,除了用start方法,也可以用 ...

  9. 2.1-Java语言基础(keyword)

    2.1  keyword watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvbXNpcmVuZQ==/font/5a6L5L2T/fontsize/400/fi ...

  10. using System.Security.Cryptography

    这个命名空间主要是用来进行加密的一些类. 加密服务: 公共网络(如 Internet)不提供实体之间安全通信的方式. 此类网络上的通信易被读取或甚至被未经授权的第三方修改. 加密有助于防止数据被查看, ...