题目链接:https://nanti.jisuanke.com/t/28412

题意:

  给出n个数的序列。问序列中有多少个区间满足,排序完之后任意两个相邻的数之差不大于1。

题解:

  用max表示区间最大值,min表示区间最小值,cnt表示区间数字的种数。那么问题转化成求max-min=cnt+1的区间数。

  用线段树维护每个区间的max-min-cnt最小值及最小值的个数,不用单独维护max,min和cnt。注意max-min >= cnt+1.

  从1~n枚举R。对于每个枚举的R,更新以R为后缀的[L,R]区间的max-min-cnt值。

  对于max和min可以用单调栈维护,max和min对max-min-cnt的贡献采用区间加减的形式而不是区间覆盖。

  对于cnt可以用一个vis[]数组维护上一次的出现位置,然后也进行区间加减。数据是1e9的,vis[]数组可以离散一下或者用map代替。

  最后对于每一个枚举的R,统计max-min-cnt的值为-1的[L,R]数。

#include <bits/stdc++.h>
using namespace std;
const int N = 1e5+;
typedef long long ll;
int t, n, k;
int nx, nn;
int lzy[N*], sum[N*], val[N*];
ll ans;
map<int, int> m;
struct node {
int p, w;
node() {}
node(int a, int b) {
p = a; w = b;
}
}mx[N], mn[N];
void push_up(int id) {
val[id] = min(val[id<<], val[id<<|]);
if(val[id<<] == val[id<<|]) sum[id] = sum[id<<]+sum[id<<|];
else if(val[id<<] < val[id<<|]) sum[id] = sum[id<<];
else sum[id] = sum[id<<|];
}
void push_down(int id) {
lzy[id<<] += lzy[id];
lzy[id<<|] += lzy[id];
val[id<<] += lzy[id];
val[id<<|] += lzy[id];
lzy[id] = ;
}
void insert(int id, int l, int r, int p) {
if(l == r) {
val[id] = -;
sum[id] = ;
return ;
}
if(lzy[id]) push_down(id);
int mid = l+r>>;
if(p<=mid) insert(id<<, l, mid, p);
else insert(id<<|, mid+, r, p);
push_up(id);
}
void update(int id, int l, int r, int ql, int qr, int v) {
if(ql<=l && r<=qr) {
lzy[id] += v;
val[id] += v;
return ;
}
if(lzy[id]) push_down(id);
int mid = l+r>>;
if(ql<=mid) update(id<<, l, mid, ql, qr, v);
if(qr>mid) update(id<<|, mid+, r, ql, qr, v);
push_up(id);
}
int main() {
scanf("%d", &t);
for(int casee = ; casee <= t; casee++) {
ans = nx = nn = ;
m.clear();
scanf("%d", &n);
memset(lzy, , sizeof(int)*(*n+));
memset(sum, , sizeof(int)*(*n+));
memset(val, 0x3f3f3f3f, sizeof(int)*(*n+));
for(int i = ; i <= n; i++) {
scanf("%d", &k);
insert(, , n, i);
int p = i, v;
while(nx > && mx[nx].w <= k) {
p = mx[nx].p, v = k-mx[nx].w;
nx--;
update(, , n, mx[nx].p+, p, v);
}
mx[++nx] = node(i, k);
p = i;
while(nn > && mn[nn].w >= k) {
p = mn[nn].p, v = k-mn[nn].w;
nn--;
update(, , n, mn[nn].p+, p, -v);
}
mn[++nn] = node(i, k);
int l;
if(m.find(k) != m.end()) l = m[k]+;
else l = ;
if(l <= i-) update(, , n, l, i-, -);
m[k] = i;
ans += sum[];
}
printf("Case #%d: %lld\n", casee, ans);
}
}

最新文章

  1. AR创意分享:儿童涂鸦遇上程序绘图
  2. activity与fragment之间传递数据
  3. Jquery--input
  4. bzoj1834
  5. &quot;provider: 命名管道提供程序, error: 40 - 无法打开到 SQL Server 的连接&quot;错误的解决方法
  6. Ruby实现wordCounter
  7. INVALID_SOCKET的值
  8. HTML5 Canvas核心技术—图形、动画与游戏开发.pdf4
  9. Android Studio 安装
  10. 利用JS实现闪烁字体
  11. Eclipse中导入第三方源码的问题和备用解决方案
  12. 使用Ajax
  13. (一)初步了解python
  14. 什么是spool系统,什么是预输入,什么是缓输出?
  15. 前端技术之--HTML
  16. GRU and LSTM
  17. 恒生UFX交易接口基本介绍说明
  18. bzoj 4358 Permu - 莫队算法 - 链表
  19. 关于PHP中浏览器禁止Cookie后,Session能使用吗?
  20. jquery原理集合

热门文章

  1. while,格式化输出
  2. maven 添加自己下载的jar包到本地仓库
  3. MyEclipse 上使用sping+hibernate+mysql
  4. Unity 对象的批处理
  5. 配置ORACLE的PRO*C环境
  6. C#获取网络图片
  7. 2.Linux文件和目录
  8. MySQL高可用之PXC安装部署
  9. APP功能性测试-3
  10. resetroot_169route_python2(用于ubuntu12.04和14.04,centos系列)