LINK:排序 此题甚好我一点思路都没有要是我当时省选此题除了模拟我恐怕想不到还可以二分 还可以线段树。。。

有点ex 不太好写 考虑 暴力显然每次给出询问我们都是可以直接sort的 无视地形无视一切直接sort 。复杂度mnlogn 30分到手。

考虑更为优秀的做法 桶排序 每次排序都是O(n)总体复杂度 nm 50分到手

考虑 不模拟做题 不断排序肯定是行不通的 如何 改变问题模型是关键之处。

然鹅 很难想到解法 思路引导一下 0 1 序列线段树树是很容易支持排序的 区间修改区间查询即可。再考虑答案是否具有单调性 从数值大小来说答案虽然是确定的 但是 显然也具有单调性(虽然有点牵强

但是我们可以不断地缩小答案的 取值范围 从而寻找到答案这是关键,从答案的值域角度来说的确可以二分。想办法不断缩小答案的值域,怎么办?
考虑最终拍好序的队列>=mid 为1 反之为0 那么我们把整个操作倒序的实现其实就是0 1 的不断排序。且最后询问的位置一定为1。因为>=当前答案。

考虑如果答案较大那么经过0 1 的排序之后最后询问的位置一定不为1 所以我们成功的缩小的值域 从而达到判定mid的效果二分可行 排序01串用上述方法搞就好了。

写完了 码力最近下降很多 可能 打代码的时候 精力不够吧。

//#include<bits/stdc++.h>
#include<iostream>
#include<cmath>
#include<ctime>
#include<algorithm>
#include<cctype>
#include<utility>
#include<queue>
#include<map>
#include<set>
#include<bitset>
#include<deque>
#include<vector>
#include<cstdio>
#include<cstdlib>
#include<iomanip>
#include<stack>
#include<string>
#include<cstring>
#define INF 1000000000
#define ll long long
#define db double
#define max(x,y) ((x)>(y)?(x):(y))
#define min(x,y) ((x)>(y)?(y):(x))
#define sum(x) t[x].sum
#define cnt(x) t[x].cnt
#define l(x) t[x].l
#define r(x) t[x].r
#define tag(x) t[x].tag
#define op(i) s[i].op
#define x(i) s[i].x
#define y(i) s[i].y
#define zz p<<1
#define yy p<<1|1
using namespace std;
char buf[<<],*fs,*ft;
inline char getc()
{
return (fs==ft&&(ft=(fs=buf)+fread(buf,,<<,stdin),fs==ft))?:*fs++;
}
inline int read()
{
int x=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<=''){x=x*+ch-'';ch=getchar();}
return x*f;
}
const int MAXN=;
int n,m,pos,sum0,sum1;
int a[MAXN],b[MAXN];
struct wy
{
int l,r;
int sum,cnt;
int tag;
}t[MAXN<<];
struct data{int op,x,y;}s[MAXN];
inline void build(int p,int l,int r)
{
l(p)=l;r(p)=r;tag(p)=-;
if(l==r){sum(p)=b[l];cnt(p)=b[l]^;return;}
int mid=(l+r)>>;
build(zz,l,mid);
build(yy,mid+,r);
sum(p)=sum(zz)+sum(yy);
cnt(p)=cnt(zz)+cnt(yy);
}
inline void pushdown(int p)
{
int mid=(l(p)+r(p))>>;
if(tag(p)==)
{
sum(zz)=(mid-l(p)+);
cnt(zz)=;
sum(yy)=r(p)-mid;
cnt(yy)=;
tag(zz)=tag(yy)=;
tag(p)=-;return;
}
sum(zz)=;
cnt(zz)=(mid-l(p)+);
sum(yy)=;
cnt(yy)=r(p)-mid;
tag(yy)=tag(zz)=;
tag(p)=-;return;
}
inline void change(int p,int l,int r,int x)
{
if(l>r)return;
if(l<=l(p)&&r>=r(p))
{
if(x==)
{
sum(p)=r(p)-l(p)+;
cnt(p)=;tag(p)=;
return;
}
cnt(p)=r(p)-l(p)+;
sum(p)=;tag(p)=;
return;
}
if(tag(p)!=-)pushdown(p);
int mid=(l(p)+r(p))>>;
if(l<=mid)change(zz,l,r,x);
if(r>mid)change(yy,l,r,x);
sum(p)=sum(zz)+sum(yy);
cnt(p)=cnt(zz)+cnt(yy);
}
inline void ask(int p,int l,int r)
{
if(l<=l(p)&&r>=r(p))
{
sum0+=cnt(p);
sum1+=sum(p);
return;
}
if(tag(p)!=-)pushdown(p);
int mid=(l(p)+r(p))>>;
if(l<=mid)ask(zz,l,r);
if(r>mid)ask(yy,l,r);
return;
}
inline int check(int x)
{
for(int i=;i<=n;++i)b[i]=a[i]>=x?:;
build(,,n);
for(int i=;i<=m;++i)
{
sum0=sum1=;
ask(,x(i),y(i));
if(!op(i))//0升序
{
//cout<<x(i)<<' '<<x(i)+sum0-1<<endl;
//cout<<x(i)+sum0<<' '<<y(i)<<endl;
change(,x(i),x(i)+sum0-,);
change(,x(i)+sum0,y(i),);
}
else
{
change(,x(i),x(i)+sum1-,);
change(,x(i)+sum1,y(i),);
}
}
sum0=sum1=;
ask(,pos,pos);
return sum1;
}
int main()
{
//freopen("1.in","r",stdin);
n=read();m=read();
for(int i=;i<=n;++i)a[i]=read();
for(int i=;i<=m;++i)
{
int op,x,y;
op=read();x=read();y=read();
s[i]=(data){op,x,y};
}
pos=read();
int l=,r=n;
while(l+<r)
{
int mid=(l+r)>>;
if(check(mid))l=mid;
else r=mid;
}
if(check(r))printf("%d\n",r);
else printf("%d\n",l);
return ;
}

最后再次回顾本题这样做法的正确性 1 我们似乎找不到一种除了模拟之外更好的方法解决本题

2 强行考虑答案的单调性 发现答案的值域显然具有单调性 想办法缩小值域 直至找到答案。

3 缩小值域方法的正确性 对于>=答案的数字看成1的话反之为0 考虑最终的序列我们可以将其抽象成0 1 串那么最后答案所在位为1。每次排序的时候我们都是将1排到前面或排到后面 最终形成一个最终的序列,于是乎我们利用等效法确定了一个01串只要这个01串最后的排序满足答案的位置为1 那么当前mid就有可能合法然后二分不断地去找那个成功与不成功的边界成功的边界就是我们寻找的答案了,正确性可以理解为等效法显然是正确的 判断的正确性显然是单调(答案可以做到比答案小的也就是1的数量更多也能做到。故此方法正确。于是就成功的解决了这个看似解决不了的问题。

排序HEOI2016/TJOI2016 二分+线段树判定的更多相关文章

  1. BZOJ4552 [Tjoi2016&Heoi2016]排序 【二分 + 线段树】

    题目链接 BZOJ4552 题解 之前去雅礼培训做过一道题,\(O(nlogn)\)维护区间排序并能在线查询 可惜我至今不能get 但这道题有着\(O(nlog^2n)\)的离线算法 我们看到询问只有 ...

  2. BZOJ4552(二分+线段树)

    要点 序列是n个不同的数,则新学到的一种策略就是二分这个位置的答案,然后可以上下调. 神奇地只关注大于还是小于mid并赋值0.1,这样m个操作的排序就能用线段树维护了! #include <cs ...

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

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

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

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

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

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

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

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

  7. hdu6070 Dirt Ratio 二分+线段树

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

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

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

  9. 【BZOJ4552】[Tjoi2016&Heoi2016]排序 二分+线段树

    [BZOJ4552][Tjoi2016&Heoi2016]排序 Description 在2016年,佳媛姐姐喜欢上了数字序列.因而他经常研究关于序列的一些奇奇怪怪的问题,现在他在研究一个难题 ...

随机推荐

  1. 6.29模拟赛 (T1:李时珍的皮肤衣 T2:马大嘴的废话 T3:SSY的队列 T4:清理牛棚);

    啊,又是考炸的一天,成功的退步了三名,啊,成共的看错了T1  的题意 ,水了80分. 第十五名就是我,额,已经有点倒数的感觉了,并且一道题都没AC  我太难了. 好了,废话不多说了,下面正式提接: 这 ...

  2. CSRF原理及防御

    CSRF原理及防御 CSRF攻击原理 CSRF攻击利用网站对用户的信任,以用户的身份发送请求来执行攻击者所要的操作,比如:转账.发邮件.修改密码.添加用户等. CSRF和XSS一样危害都特别大,只不过 ...

  3. selenium:selenium.common.exceptions.WebDriverException: Message: 'geckodriver' executable needs to be in PATH.

    可用链接: 1.http://blog.csdn.net/heatdeath/article/details/71136174 2.https://www.cnblogs.com/yousuosiys ...

  4. java 基本语法(十五)Lambda (二)函数式接口

    1.函数式接口的使用说明> 如果一个接口中,只声明了一个抽象方法,则此接口就称为函数式接口.> 我们可以在一个接口上使用 @FunctionalInterface 注解,这样做可以检查它是 ...

  5. redis(十二):Redis 集合(Set)

    Redis 集合(Set) Redis 的 Set 是 String 类型的无序集合.集合成员是唯一的,这就意味着集合中不能出现重复的数据. Redis 中集合是通过哈希表实现的,所以添加,删除,查找 ...

  6. JavaScript动画实例:曲线的绘制

    在“JavaScript图形实例:曲线方程”一文中,我们给出了15个曲线方程绘制图形的实例.这些曲线都是根据其曲线方程,在[0,2π]区间取一系列角度值,根据给定角度值计算对应的各点坐标,然后在计算出 ...

  7. python3利用cryptography 进行加密和解密

    我们的日常工作中,一定会遇到需要加密的数据,比如:密码.私密信息... ... 我们不仅要对他们进行加密,更需要对他们进行解密,因为毕竟我们的用户应该不会看得懂加密过后的字符串吧!!! 在python ...

  8. 为什么大家都在用Fiddler?

    在我们做接口测试的时候,经常需要验证发送的消息是否正确,或者在出现问题的时候,查看手机客户端发送给server端的包内容是否正确,就需要用到抓包工具.常用的抓包工具有fiddler.wireshark ...

  9. Salesforce LWC学习(十九) 针对 lightning-input-field的label值重写

    本篇参考: https://salesforcediaries.com/2020/02/24/how-to-override-lightning-input-field-label-in-lightn ...

  10. 学习jvm(一)--java内存区域

    前言 通过学习深入理解java虚拟机的教程,以及自己在网上的查询的资料,做一个对jvm学习过程中的小总结. 本文章内容首先讲解java的内存分布区域,之后讲内存的分配原则以及内存的监控工具.再下来会着 ...