bzoj P1058 [ZJOI2007]报表统计——solution
1058: [ZJOI2007]报表统计
Time Limit: 15 Sec Memory Limit: 162 MB Submit: 4099 Solved: 1390 [Submit][Status][Discuss]
Description
Input
Output
对于每一个“MIN_GAP”和“MIN_SORT_GAP”命令,输出一行答案即可。
Sample Input
Sample Output
HINT
N , M ≤500000 对于所有的数据,序列内的整数不超过5*10^8。
http://www.lydsy.com/JudgeOnline/problem.php?id=1058
- by bzoj
首先明确每次插入的位置可以通过简单的记录来快速得知,
然后分开考虑两种询问
1询问排序后的相邻元素间的最小差值,
如果维护排序后相邻元素间差值的话,元素的加入影响差值,应该是一个有加入有删除的操作,
而事实上由于每一次删除差值的诱因一定是新加入的元素夹在原来的两个元素之间,破坏了这两个元素间的差值,
这意味着删除的差值一定不如新产生的差值小,
于是可以视作没有删除;
那就是一个单纯比较取最小的过程了;
为了找到新产生了哪些差值,笔者这里选用了set对报表中的元素进行动态排序加二分查找;
这个询问的答案只会越来越小,最后可能到零,记得到零后记录一下,省一点多余的操作
2询问当前没有排序的序列的相邻元素的最小值,
如果维护未排序时相邻元素间差值的话,元素的加入影响差值,这里真的是一个有加入有删除的操作了;
每次在i与i+1间插入一个元素x,在维护差值的数据结构中找到abs(a[i+1]-a[i])删掉,然后加入abs(x-a[i])和abs(x-a[i+1]);
这里可以用平衡树维护
笔者这里偷懒直接用动态加点线段树做了,本来内存巨大应该过不了,遂偷偷改小数组,没想到竟然bzoj和luogu的数据都水过来了,暗爽
——现在写题解时想想,好像只要写个set维护就完事了
——结果就是道STL题啊!!!!!!!!!!!!
代码:
#include<map>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
map <int ,int >MAP;
int id_now[500010];
struct ss{
int num,las,nex;
}ctn[1000010];
struct DT{
int size,ch[2];
}data[10000000];
int top,tot,n,m;
bool flag;
char s[20];
inline void in(int &ans)
{
ans=0;bool p=false;char ch=getchar();
while((ch>'9' || ch<'0')&&ch!='-') ch=getchar();
if(ch=='-') p=true,ch=getchar();
while(ch<='9'&&ch>='0') ans=ans*10+ch-'0',ch=getchar();
if(p) ans=-ans;
}
void insert(int ,int ,int ,int ,int );
int get_MIN(int ,int ,int );
int main()
{
int i,j,k,ans2=1000000000;
map <int ,int > :: iterator iter;
in(n),in(m);
tot=n,top=1,flag=false;
for(i=1;i<=n;i++){
ctn[i].las=i-1;
ctn[i].nex=(i+1)%(n+1);
in(ctn[i].num);
if(ctn[i].las)
insert(0,1000000000,1,abs(ctn[i].num-ctn[ctn[i].las].num),1);
if(MAP.count(ctn[i].num)||flag)
flag=true;
else{
iter=MAP.upper_bound(ctn[i].num);
if(iter!=MAP.end())
ans2=min(ans2,iter->first-ctn[i].num);
if(iter!=MAP.begin())
iter--,ans2=min(ans2,ctn[i].num-iter->first);
MAP[ctn[i].num]=i;
}
id_now[i]=i;
}
for(i=1;i<=m;i++){
scanf("%s",s);
if(s[0]=='I'){
in(j),in(k);
ctn[++tot].num=k;
ctn[tot].nex=ctn[id_now[j]].nex;
ctn[ctn[id_now[j]].nex].las=tot;
ctn[tot].las=id_now[j];
ctn[id_now[j]].nex=tot;
ctn[0].nex=ctn[0].las=ctn[0].num=0;
if(ctn[tot].las)insert(0,1000000000,1,abs(k-ctn[ctn[tot].las].num),1);
if(ctn[tot].nex)insert(0,1000000000,1,abs(k-ctn[ctn[tot].nex].num),1);
if(ctn[tot].las&&ctn[tot].nex)insert(0,1000000000,1,abs(ctn[ctn[tot].las].num-ctn[ctn[tot].nex].num),-1);
if(!flag){
if(MAP.count(ctn[tot].num)){
flag=true,id_now[j]=tot;continue;
}
iter=MAP.upper_bound(k);
if(iter!=MAP.end())ans2=min(ans2,iter->first-k);
if(iter!=MAP.begin())iter--,ans2=min(ans2,k-iter->first);
MAP[k]=tot;
}
id_now[j]=tot;
}
if(s[0]=='M'&&s[4]=='G')
printf("%d\n",get_MIN(0,1000000000,1));
if(s[0]=='M'&&s[4]=='S')
printf("%d\n",(flag^1)*ans2);
}
return 0;
}
void insert(int l,int r,int now,int lim,int x){
int mid=(l+r)>>1;
if(l==r){
data[now].size+=x;
return ;
}
if(lim<=mid){
if(!data[now].ch[0])data[now].ch[0]=++top;
insert(l,mid,data[now].ch[0],lim,x);
}
else{
if(!data[now].ch[1])data[now].ch[1]=++top;
insert(mid+1,r,data[now].ch[1],lim,x);
}
data[now].size=data[data[now].ch[0]].size+data[data[now].ch[1]].size;
}
int get_MIN(int l,int r,int now){
if(l==r)return l;
int mid=(l+r)>>1;
if(data[data[now].ch[0]].size)
return get_MIN(l,mid,data[now].ch[0]);
else
return get_MIN(mid+1,r,data[now].ch[1]);
}
bzoj P1058 [ZJOI2007]报表统计——solution的更多相关文章
- BZOJ 1058: [ZJOI2007]报表统计( 链表 + set )
这种题用数据结构怎么写都能AC吧...按1~N弄个链表然后每次插入时就更新答案, 用set维护就可以了... --------------------------------------------- ...
- bzoj 1058: [ZJOI2007]报表统计 (Treap)
链接:https://www.lydsy.com/JudgeOnline/problem.php?id=1058 题面; 1058: [ZJOI2007]报表统计 Time Limit: 15 Sec ...
- bzoj 1058: [ZJOI2007]报表统计
Description 小Q的妈妈是一个出纳,经常需要做一些统计报表的工作.今天是妈妈的生日,小Q希望可以帮妈妈分担一些工 作,作为她的生日礼物之一.经过仔细观察,小Q发现统计一张报表实际上是维护一个 ...
- BZOJ 1058: [ZJOI2007]报表统计 multiset + 卡常
Code: #include<bits/stdc++.h> #define maxn 600000 #define inf 1000000000 using namespace std; ...
- [BZOJ 1058] [ZJOI2007] 报表统计 【平衡树】
题目链接:BZOJ - 1058 题目分析 这道题看似是需要在序列中插入一些数字,但其实询问的内容只与相邻的元素有关. 那么我们只要对每个位置维护两个数 Ai, Bi, Ai 就是初始序列中 i 这个 ...
- bzoj 1058 [ZJOI2007]报表统计(set)
[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=1058 [题意] 一个序列,提供插入,查询相邻最小差值,查询任意最小差值的操作. [思路 ...
- bzoj 1058: [ZJOI2007]报表统计【set】
我想写FHQtreap的!是set自己跑进代码的!因为太好写了 是有点慢--洛谷上不吸氧会T一个点 就是,用一个set p维护所有点值,ans维护MIN_SORT_GAP的答案,每次insert一个点 ...
- [ZJOI2007]报表统计(splay,堆)
[ZJOI2007]报表统计(luogu) Description 题目描述 Q的妈妈是一个出纳,经常需要做一些统计报表的工作.今天是妈妈的生日,小Q希望可以帮妈妈分担一些工作,作为她的生日礼物之一. ...
- bzoj1058: [ZJOI2007]报表统计
set.操作:insert(u,v)在u后面插入v,若u后面已插入过,在插入过的后面插入.mingap求出序列两两之间差值的最小值.minsortgap求出排序后的序列两两之间的最小值.用multis ...
随机推荐
- 攻防组网之—-VMware路由器安装设置
本文作者:i春秋作家——红发香克斯 前言 VMWare功能很强大,我一直有个想法是能不能用一台高配的主机利用VM虚拟化出一个或多个真实的子网,或者子网里面还有子网,其中使用VM自动的功能可以实现多个网 ...
- webpack快速入门——CSS中的图片处理
1.首先在网上随便找一张图片,在src下新建images文件夹,将图片放在文件夹内 2.在index.html中写入代码:<div id="pic"></div& ...
- node 无脑生成小程序二维码图
RT 新建createwxaqrcode.js: const request = require('request') const fs = require('fs') // eg:生成购物车列表圆形 ...
- [微信小程序]——bug记录
记录日常开发小程序遇到的一些小问题: input 输入框(unfixed) 描述:输入框focus的时候,placeholder会往上面跳动一下 当 scroll-view 遇上 fixed 描述:给 ...
- [Swift实际操作]七、常见概念-(1).范围Range、ClosedRange和NSRange的使用实际操作
本文将为你解析区间的概念.在对字符串进行处理时,经常会使用到区间.例如获得字符串中从某个位置开始到另一个位置之间的内容. 首先导入需要使用到的框架 import Foundation 区间分为闭区间和 ...
- iOS 代码混淆的简单使用
1.工具下载 http://stevenygard.com/projects/class-dump/ 选择dmg安装包 2.打开终端输入:open/usr/local/bin 3. 4.修改权限在 ...
- .Net Core 发布WindowsServices
项目代码文件夹 执行命令 dotnet publish -c Release -r win-x64
- EJB3 事物
在ejb3中事物分为两种类型:容器管理的事物(CMT).Bean管理的事物(BMT) 1.容器管理的事物(CTN) 是EJB默认的事物管理方式,即以对应的方法起始和结束来由EJB容器确定事务的始末边界 ...
- 由一段代码谈前端js优化和编码规范(一) 分类: JavaScript 2015-03-21 12:43 668人阅读 评论(1) 收藏
这段代码是撸主刚毕业那会写的,主要是实现一个左侧的导航条的折叠功能.当时实现的比较简陋,每次在导航条增加新的项目的时候,都要手动去修改js代码中写死的索引...确实是比较恼火的,后来就修改了一下,能够 ...
- Windows Server2016服务器系统创建域服务器
原先是有图片,因为图片是直接粘贴上来的,发布之后图片都看见了,然后都使用上传图片的方式才搞定,这也是博客园比较坑的地方: 也可以查看该链接含图片: http://www.cnblogs.com/all ...