BZOJ1058或洛谷1110 [ZJOI2007]报表统计
BZOJ原题链接
洛谷原题链接
STL
本题可以直接使用\(\mathtt{STL\ multiset}\)水过去。
因为本题插入数的操作实际上就是将原数列分为\(n\)段,在每一段的末尾插入数,所以我们只需维护每一段的开头和末尾两个数,这样更新相邻差值时只需考虑插入数与原末尾和下一段的开头两个数的差值就好。
而维护这个差值,只开一个\(\mathtt{multiset}\)就好(其中是所有相邻差值)。当插入一个数时,先将原本的末尾和后一段开头的差值从\(\mathtt{multiset}\)里删除,再插入新的差值即可。
而所有元素中最接近的两个元素的差值,实际上就是找每个数的前驱和后继,再作差取最小值。
同样开个\(\mathtt{multiset}\)来维护(其中是所有元素),当插入数时,找其前驱和后继作差取\(\min\)即可。
#include<cstdio>
#include<set>
using namespace std;
const int N = 5e5 + 10;
multiset<int> S, D;
int st[N], ed[N], mi = 1e9, n, l;
char C[20];
inline int re()
{
int x = 0;
char c = getchar();
bool p = 0;
for (; c < '0' || c > '9'; c = getchar())
p |= c == '-';
for (; c >= '0' && c <= '9'; c = getchar())
x = x * 10 + c - '0';
return p ? -x : x;
}
inline void re_l()
{
char c = getchar();
for (l = 0; (c < 'A' || c > 'Z') && c != '_'; c = getchar());
for (; (c >= 'A' && c <= 'Z') || c == '_'; c = getchar())
C[l++] = c;
}
inline int jd(int x) { return x < 0 ? -x : x; }
inline int minn(int x, int y) { return x < y ? x : y; }
inline void update_S(int x)
{
multiset<int>::iterator it = S.lower_bound(x), k = it;
mi = minn(mi, minn(jd(x - *it), jd(x - *(--k))));
S.insert(x);
}
inline void update_D(int x, int y)
{
if (x ^ n)
D.erase(D.find(jd(st[x + 1] - ed[x]))), D.insert(jd(st[x + 1] - y));
D.insert(jd(y - ed[x]));
ed[x] = y;
}
int main()
{
int i, m, x, y;
n = re(); m = re();
S.insert(-1e9); S.insert(1e9);
for (i = 1; i <= n; i++)
update_S(st[i] = ed[i] = re());
for (i = 2; i <= n; i++)
D.insert(jd(st[i] - ed[i - 1]));
for (i = 1; i <= m; i++)
{
re_l();
if (C[0] == 'I')
{
x = re(); y = re();
update_S(y); update_D(x, y);
}
else
if (C[4] == 'S')
printf("%d\n", mi);
else
printf("%d\n", *D.begin());
}
return 0;
}
平衡树+线段树/堆/……
若不用\(\mathtt{STL}\),只需将其中一个\(\mathtt{multiset}\)改为平衡树,另一个改为线段树/堆之类的维护最小值的数据结构即可。
这里我用的是\(\mathtt{Splay}\)和线段树。
平衡树同样是插入所有元素,找前驱后继作差取最小值。
而线段树是插入每一段的末尾与其下一段的开头的差,维护一个最小值,而段内的相邻差值则再开一个变量维护最小值,对该询问的答案就是这两个取\(\min\)。
#include<cstdio>
using namespace std;
const int N = 5e5 + 10;
struct sp {
int so[2], fa, v;
};
sp tr[N << 1];
int MI[N << 2], st[N], ed[N], ro, SP, l;
char C[20];
inline int re()
{
int x = 0;
char c = getchar();
bool p = 0;
for (; c < '0' || c > '9'; c = getchar())
p |= c == '-';
for (; c >= '0' && c <= '9'; c = getchar())
x = x * 10 + c - '0';
return p ? -x : x;
}
inline void re_l()
{
char c = getchar();
for (l = 0; (c < 'A' || c > 'Z') && c != '_'; c = getchar());
for (; (c >= 'A' && c <= 'Z') || c == '_'; c = getchar())
C[l++] = c;
}
inline int jd(int x) { return x < 0 ? -x : x; }
inline int minn(int x, int y) { return x < y ? x : y; }
inline int maxn(int x, int y) { return x > y ? x : y; }
inline int who(int x) { return tr[tr[x].fa].so[0] ^ x ? 1 : 0; }
inline void ch(int x, int fa, int lr) { tr[fa].so[lr] = x; tr[x].fa = fa; }
inline void rtt(int x)
{
int y = tr[x].fa, r = tr[y].fa, soy = who(x), sor = who(y);
ch(tr[x].so[soy ^ 1], y, soy);
ch(y, x, soy ^ 1); ch(x, r, sor);
}
void sy(int x, int y)
{
int z = tr[x].fa;
if (!(ro ^ y))
ro = x;
y = tr[y].fa;
for (; tr[x].fa ^ y; z = tr[x].fa)
if (!(tr[z].fa ^ y))
rtt(x);
else
{
who(x) ^ who(z) ? rtt(x) : rtt(z);
rtt(x);
}
}
inline int newnode(int x, int fa)
{
tr[++SP].fa = fa;
tr[SP].v = x;
return SP;
}
void ins(int x)
{
if (!ro)
ro = newnode(x, 0);
else
for (int y, k = ro; ; k = tr[k].so[y])
{
if (!(tr[k].v ^ x))
return;
if (!tr[k].so[y = x < tr[k].v ? 0 : 1])
{
int nw = newnode(x, k);
tr[k].so[y] = nw; sy(nw, ro);
return;
}
}
}
inline int qu_pre(int x)
{
int s = -1e9;
for (int k = ro; k; k = tr[k].so[x <= tr[k].v ? 0 : 1])
if (x >= tr[k].v)
s = maxn(s, tr[k].v);
return s;
}
inline int qu_suc(int x)
{
int s = 1e9;
for (int k = ro; k; k = tr[k].so[x >= tr[k].v ? 1 : 0])
if (x <= tr[k].v)
s = minn(s, tr[k].v);
return s;
}
void pp(int r) { MI[r] = minn(MI[r << 1], MI[r << 1 | 1]); }
void bu(int r, int x, int y)
{
if (!(x ^ y))
MI[r] = jd(st[x] - st[x - 1]);
else
{
int mid = (x + y) >> 1;
bu(r << 1, x, mid);
bu(r << 1 | 1, mid + 1, y);
pp(r);
}
}
void upd(int r, int x, int y, int q, int k)
{
if (!(x ^ y))
MI[r] = k;
else
{
int mid = (x + y) >> 1;
q <= mid ? upd(r << 1, x, mid, q, k) : upd(r << 1 | 1, mid + 1, y, q, k);
pp(r);
}
}
int main()
{
int i, n, m, x, y, mi = 1e9, mis = 1e9;
n = re(); m = re();
st[0] = st[n + 1] = 1e9;
for (i = 1; i <= n; i++)
{
st[i] = ed[i] = re();
if (i ^ 1)
mis = minn(mis, minn(jd(qu_pre(st[i]) - st[i]), jd(qu_suc(st[i]) - st[i])));
ins(st[i]);
}
bu(1, 1, n);
for (i = 1; i <= m; i++)
{
re_l();
if (C[0] == 'I')
{
x = re(); y = re();
mis = minn(mis, minn(jd(qu_pre(y) - y), jd(qu_suc(y) - y)));
ins(y);
mi = minn(mi, jd(y - ed[x]));
upd(1, 1, n, x, jd(st[x + 1] - y));
ed[x] = y;
}
else
if (C[4] == 'S')
printf("%d\n", mis);
else
printf("%d\n", minn(mi, MI[1]));
}
return 0;
}
BZOJ1058或洛谷1110 [ZJOI2007]报表统计的更多相关文章
- 洛谷.1110.[ZJOI2007]报表统计(Splay Heap)
题目链接 附纯SplayTLE代码及主要思路: /* 可以看做序列有n段,Insert是每次在每一段最后插入一个元素 只有插入,没有删除,所以插入一个元素对于询问1影响的只有该元素与前边一个元素(同段 ...
- 洛谷.1110.[ZJOI2007]报表统计(Multiset Heap)
题目链接 主要思路 /* 对于询问1,用堆代替multiset/Splay 对于询问2,multiset 1.注意哨兵元素 2.注意multiset中删除时是删除某元素的一个位置,而不是这个元素!这个 ...
- 洛谷.1110.[ZJOI2007]报表统计(Multiset)
题目链接 主要思路 /* 其实只需要multiset即可 对于询问1,删除.插入差值,输出最小元素 对于询问2,插入后用前驱后继更新 1.注意哨兵元素 2.注意multiset中删除时是删除某元素的一 ...
- 洛谷 P1110 [ZJOI2007]报表统计 解题报告
P1110 [ZJOI2007]报表统计 题目描述 \(Q\)的妈妈是一个出纳,经常需要做一些统计报表的工作.今天是妈妈的生日,小\(Q\)希望可以帮妈妈分担一些工作,作为她的生日礼物之一. 经过仔细 ...
- 2018.11.09 洛谷P1110 [ZJOI2007]报表统计(multiset)
传送门 sb题. 直接用两个multisetmultisetmultiset维护相邻两个数的差值和所有数的前驱后继. 插入一个数的时候更新一下就行了. 代码: #include<bits/std ...
- 【BZOJ1058】[ZJOI2007]报表统计 STL
[BZOJ1058][ZJOI2007]报表统计 Description 小Q的妈妈是一个出纳,经常需要做一些统计报表的工作.今天是妈妈的生日,小Q希望可以帮妈妈分担一些工作,作为她的生日礼物之一.经 ...
- bzoj1058: [ZJOI2007]报表统计
set.操作:insert(u,v)在u后面插入v,若u后面已插入过,在插入过的后面插入.mingap求出序列两两之间差值的最小值.minsortgap求出排序后的序列两两之间的最小值.用multis ...
- 洛谷 P1169 [ZJOI2007]棋盘制作
2016-05-31 14:56:17 题目链接: 洛谷 P1169 [ZJOI2007]棋盘制作 题目大意: 给定一块矩形,求出满足棋盘式黑白间隔的最大矩形大小和最大正方形大小 解法: 神犇王知昆的 ...
- BZOJ 1058: [ZJOI2007]报表统计( 链表 + set )
这种题用数据结构怎么写都能AC吧...按1~N弄个链表然后每次插入时就更新答案, 用set维护就可以了... --------------------------------------------- ...
随机推荐
- 入门Spring ioc
简单的来记录一下自己的SSM框架入门--------IOC篇段 ioc(控制反转 -将对象的创建的权利从类型本身来创建,来交给spring工厂来创建)的配置. <bean>:是可以指spr ...
- 数组Array的API1
数组的方法arr.includes()arr.every(fn(val,i))arr.some(fn(val,i))arr.filter(fn(val,i))arr.map(fn(val,i))ar. ...
- Spring 框架用到的 9 个设计模式汇总!
1. 简单工厂 又叫做静态工厂方法(StaticFactory Method)模式,但不属于23种GOF设计模式之一. 简单工厂模式的实质是由一个工厂类根据传入的参数,动态决定应该创建哪一个产品类 ...
- EasyUI 1.3.2 中 Combobox自动检索 键盘上下选择Bug问题
EasyUI 自带的Combobox控件,提供了下拉列值自动检索功能. 在用到的EasyUI 1.3.2版本中还是有点问题,在键盘上下键移动选择过程中只能定位在第一个,不能正常向下移动 问题解决方式: ...
- [Linux]系统管理: 进程管理(ps/top/pstree/kill/pkill), 工作管理, 系统资源查看, 系统定时任务
进程管理:查看与终止 进程查看 1. 进程是正在执行的程序或命令. 2. 进程管理的作用: 判断服务器健康状态, 查看系统中所有进程 杀死进程 3. 查看系统中所有进程 ps aux # 查看系 ...
- Sql Server数据库之多表查询
一.连接查询 概念:根据两个表或多个表的列之间的关系,从这些表中查询数据 目的:实现多表查询操作 语法:From join_table join_type join_table[ON(join_con ...
- ARM-start.s注释(2410Init.s)
本人只是做个笔记保存一下. 来源:http://blog.itpub.net/13771794/viewspace-478463/ ;================================= ...
- Dynamic Method Binding in Delphi 动态方法绑定
Dynamic Method Binding in Delphi 动态方法绑定 https://docs.dataabstract.com/Delphi/AdvancedTopics/Dynamic ...
- vue中的一些知识点--多看文档
重温vue,一些知识点简单记录. 1.我们都知道当数据变化时,视图会重新渲染.注意:只有当vue实例被创建时,data中存在的属性才是响应式的.后续新添加的属性不会触发视图变化. 使用 Object. ...
- C/C++控制台接收不到鼠标消息-【解决办法】
控制台编程中,使用了鼠标操作,遇到了控制台无法接收到鼠标消息的问题,可尝试一下办法解决 [win10系统] 在控制台标题栏右键-默认值-选项,将一下对勾取消 然后调用如下函数: HANDLE hIn ...