题目





像素有点低啊~

算了凑合一下就好啦~

题目大意

给你一个首尾相接的数列,每次对一个区间进行操作:

顺时针操作,如果当前值比vvv大,就交换。输出最后的vvv。


比赛思路

首先这题的时限这么仁慈,一定有天大玄机。

并且一看这题,就感觉像是一个数据结构。

首先在想链表,但显然这题链表不可做。

然后一直在想带修主席树。

没想出来……

最后弃疗,直接打了个暴力。

WTF?15分?说好的25分呢?

然而实际上这题很没良心地捆绑数据,将10分和另外15分绑在一起了。

出题人,你怎么能这样子啊?你忍心吗?


正解

这题WMY大佬说可以用带修主席树做。

刚了一个下午,最终,他弃疗了……

原因是标记不好下传。

实际上正解是分块。

首先看到时间复杂度,我们就应该想到这题可以随意给你搞事情。

然而我就是没有想到分块!!!

首先,对于一个区间,如果有一个操作经过了这个区间,设区间中的最大值为mxmxmx。若mx>vmx>vmx>v,则交换,否则继续。

这个结论是很显然的,依靠这个结论可以再拿15分。

我们可以将其分块,每个块的大小为KKK。对于每个块,我们维护一个大根堆,存下这个块里面的所有值。

如果处理整块,就直接和最大值比较,然后像之前一样操作。并且,在这个块上打一个标记。

如果处理散块,就要将这个散块还原,然后暴力搞一遍。

如何还原呢?

首先,对于每个块,我们将标记存在一个小根堆里面。

在还原的时候,我们从左到右扫,对于每个值,用小根堆的堆顶操作。如果ai>va_i>vai​>v,就交换(也就是将vvv弹出,将aia_iai​加入,并且改变aia_iai​的值)

最后将标记清空。

这就还原了整个块了,然后暴力搞一遍,重构大根堆。

那么问题来了,为什么每次用小根堆的堆顶操作?

可以感性地理解一下:

对于第一个,这些标记的操作都会对它有操作。如果当前的这个值大于vvv,那么就要被交换。而交换那么多遍,最后真正能对它做出影响的是最小的vvv,其它的东西都会传到后面去。

然后对于后面的,也是一样的道理。

和氧化还原反应好像啊!——ZJQ

所以整块的时间复杂度是O(qnKlg⁡K)O(q\frac{n}{K}\lg K)O(qKn​lgK),散块的时间复杂度是O(qKlg⁡q)O(qK\lg q)O(qKlgq)

然后平衡规划一下,得出KKK大概为n\sqrt nn​。

然而分块的常数是有差异的,所以KKK的取值据实际而定。

我取了800800800。当我取600600600时,程序就崩了,或许是堆太多了吧。(我用了STL的堆)


代码

using namespace std;
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#define N 400000
#define K 800
int n,q;
int a[N];
int m;
#define bel(x) ((x)/K)
#define nxt(x) (((x)+1==m)?(0):((x)+1))
priority_queue<int> h[N/K];
priority_queue<int,vector<int>,greater<int> > bz[N/K];
inline void pushdown(int b,int l,int r,int &v){//处理散块
//还原
if (!bz[b].empty()){
for (int i=b*K;i<b*K+K && i<n;++i){
int t=bz[b].top();
if (a[i]>t){
bz[b].pop();
bz[b].push(a[i]);
a[i]=t;
}
}
while (!bz[b].empty())
bz[b].pop();
}
//暴力处理
for (int i=l;i<=r;++i)
if (a[i]>v)
swap(a[i],v);
//重构
while (!h[b].empty())
h[b].pop();
for (int i=b*K;i<b*K+K && i<n;++i)
h[b].push(a[i]);
}
inline void getinto(int b,int &v){//表示处理整块,v进入b中,再出来
int t=h[b].top();
if (t>v){
h[b].pop();
h[b].push(v);
bz[b].push(v);
v=t;
}
}
int main(){
scanf("%d%d",&n,&q);
for (int i=0;i<n;++i)
scanf("%d",&a[i]);
m=(n-1)/K+1;
for (int i=0;i<m;++i)
for (int j=0;j<K && i*K+j<n;++j)
h[i].push(a[i*K+j]);
while (q--){
int l,r,v;
scanf("%d%d%d",&l,&r,&v);
l--,r--;
int bl=bel(l),br=bel(r);
if (bl==br){
if (l<=r)
pushdown(bl,l,r,v);
else{
pushdown(bl,l,min(bl*K+K-1,n-1),v);
for (int i=nxt(bl);i!=br;i=nxt(i))
getinto(i,v);
pushdown(br,br*K,r,v);
}
}
else{
if (l==bl*K)
getinto(bl,v);
else
pushdown(bl,l,min(bl*K+K-1,n-1),v);
for (int i=nxt(bl);i!=br;i=nxt(i))
getinto(i,v);
if (r==min(br*K+K-1,n-1))
getinto(br,v);
else
pushdown(br,br*K,r,v);
}
printf("%d\n",v);
}
return 0;
}

我才发现原来要打个cpp才能有颜色,我之前打的都是C++,天哪,博客更新之后就是不一样!


总结

看见时限大的题,往分块方面想一想,或许就能很好解决了。

分块的优点,在于它只需要对整块和散块分块处理,也就是说,不像线段树那样下传时这么复杂。

还有,这题有没有其他的方法。比如,分块套分块(手动滑稽)

JZOJ5967 常数国的更多相关文章

  1. Before NOIP 2018

    目录 总结 刷题 2018 - 9 - 24 2018 - 9 - 25 2018 - 9 - 26 2018 - 9 - 27 2018 - 9 - 28 2018 - 9 - 29 2018 - ...

  2. [jzoj NOIP2018模拟10.23]

    丢分主要是下面几个方面: 1.T2代码交错了,有个特判没写丢了10分 2.T1线段树加等差数列写错了(其实二维差分就可以,但我当时不会) 3.T3思考再三还是为了10分写上了主席树,还是写错了 总体评 ...

  3. 解析大型.NET ERP系统 多国语言实现

    实现多国语言有许多种实现方案,无外乎是一种字符串替换技术,将界面控件的文本标签替换成相应语言的文字..NET Windows Forms实现多国语言的方法有以下几种: 1 .NET的方案,使用资源文件 ...

  4. [LeetCode] Insert Delete GetRandom O(1) - Duplicates allowed 常数时间内插入删除和获得随机数 - 允许重复

    Design a data structure that supports all following operations in average O(1) time. Note: Duplicate ...

  5. [LeetCode] Insert Delete GetRandom O(1) 常数时间内插入删除和获得随机数

    Design a data structure that supports all following operations in average O(1) time. insert(val): In ...

  6. Flex 1046: 找不到类型,或者它不是编译时常数;1180: 调用的方法 CompPropInfo 可能未定义

    导入项目之后一直报这个错误, 1046: 找不到类型,或者它不是编译时常数: 1180: 调用的方法 CompPropInfo 可能未定义 想这应该是没有把当前这个类编译进项目当中,找了半天也没有找到 ...

  7. 高质量,高效率的多国语言软件开发(Web/PC/Mobile),使用接口约束/调用不同语言资源

    偶然间翻出了几年前写的一个小程序,把当时的资料整理整理分享一下. 当时为了给自己的软件实现多国语言功能,而开发的辅助工具:SE String Resource. 这是当时基于自己另一款 IDE 软件抽 ...

  8. ARM的常数表达式

    ARM的常数表达式   如果说Intel指令中的立即数,相信大家都很熟悉.类似的,Arm指令中的“立即数”就是常数表达式.之所以称为常数表达式,而不称为立即数是有原因的. Intel指令属于CISC指 ...

  9. Atitti 存储引擎支持的国内点与特性attilax总结

    Atitti 存储引擎支持的国内点与特性attilax总结 存储引擎处理的事情: · 并发性:某些应用程序比其他应用程序具有很多的颗粒级锁定要求(如行级锁定). · 事务支持:并非所有的应用程序都需要 ...

随机推荐

  1. Django项目:堡垒机(Linux服务器主机管理系统)--03--03堡垒机在Linux系统里记录会话日志02/02

    #main.py #本文件写所有的连接交互动作程序 # ————————————————03堡垒机在Linux系统里记录会话日志 开始———————————————— from Fortress im ...

  2. go网络库cellent实现socket聊天功能

    一 .介绍 cellnet是一个组件化.高扩展性.高性能的开源服务器网络库 git地址:https://github.com/davyxu/cellnet 主要使用领域: 游戏服务器 方便定制私有协议 ...

  3. Kmeans算法实现

    下面的demo是根据kmeans算法原理实现的demo,使用到的数据是kmeans.txt 1.658985 4.285136 -3.453687 3.424321 4.838138 -1.15153 ...

  4. SpringBoot_05_ssm拦截器和默认欢迎页面的设置

    1.在springBoot下通过使用拦截器完成在没有登陆的前提下,不允许访问其他资源 编写拦截器,要实现HandlerInterceptor @Component public class UserI ...

  5. jedis3.1.0在weblogic(jdk1.6)中无法运行

    文章目录 错误 探索 总结 错误 在tomcat中运行是没有问题的,可是在weblogic中是不能够运行的,weblogic中的jdk客户要求是1.6的. 如果更换版本jedis2.9.0是没有问题的 ...

  6. STM32F4X 关于MDK上虚拟串口调试

    1. 下载安装VSPD 自行百度安装后,利用VSPD将PC上的两个虚拟串口连接起来.如图我将COM1 和COM2连接起来. a. 点击Addr pair. 可以看到Virtual ports上将两个虚 ...

  7. <Django> MVT三大块之Template(模板)

    1.模板简介 创建项目,基本配置 第一步:配置数据库 第二步:创建APP,配置APP 第三步:配置模板路径 第四步:配置分发urls.py(APP里面的) 根目录下,增加命名空间namespace,作 ...

  8. JPA默认方法查询遇到转JSON的处理

    JPA提供的findAll等查询方法在有关联的对象时 比如:在查userInfo @Entity@Table(name = "user_info")public class Use ...

  9. WebException: The underlying connection was closed: Could not establish trust relationship for the SSL/TLS secure channel

    关于这个异常的问题网上有很多的解决方案. 最为靠谱的有: http://www.cnblogs.com/hjf1223/archive/2007/03/14/674502.html(若因为链接而导致不 ...

  10. login-Linux必学的60个命令

    1.作用 login的作用是登录系统,它的使用权限是所有用户. 2.格式 login [name][-p ][-h 主机名称] 3.主要参数 -p:通知login保持现在的环境参数. -h:用来向远程 ...