区间(interval)

题目描述

  zht有一个长度为n的排列P,现在zht想知道,有多少个由连续整数组成的区间[l,r][l,r]可以由PP中的两个区间[a,b],[c,d]拼出,其中1≤a≤b<c≤d≤n

  例如P=[1,5,2,4,6,3,那么数字区间[5,6][5,6]可以由PP的区间[2,2][2,2]与[5,5][5,5]拼出。换句话说PP中这两个区间数字的并集为[l,r]

输入

第一行一个整数nn表示排列中数字个数。

第二行nn个数表示排列。

输出

一行一个正整数表示答案。

样例输入

5
1 4 5 3 2

样例输出

10

提示

数据范围:

10%的数据:n≤20n≤20

40%的数据:n≤2000n≤2000

另有10%的数据:Pi=iPi=i

100%的数据: 1≤n≤3∗105


solution

考虑dp 令f[l][r]表示权值取l,r时会形成多少联通块。

我们枚举r,假设已经知道了f[1~r-1][r-1] 问题是如何快速求出f[1~r][r]

我们假设r在排列中的位置为x 找出p[x-1]和p[x+1]

然后分类讨论L的位置,决定转移是否要加1或减一

可以线段树优化。

现在还有个问题:怎么求f值为1和2的个数

我们可以存最小值,次小值和出现次数。

因为不会减到0,所以不用推来推去

好高级的线段树

注意不能写bj>0 要写bj!=0!!!!!

#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cmath>
#define maxn 300005
#define ls k<<1
#define rs k<<1|1
#define inf 1e9
#define ll long long
using namespace std;
int n,a[maxn],p[maxn];
ll ans=0;
struct node{
int l,r;
ll ma,va,mb,vb,bj;
void out(){
cout<<"l: "<<l<<' '<<"r "<<r<<' '<<"a "<<ma<<' '<<va<<' '<<"b "<<mb<<' '<<vb<<' '<<endl;
}
}tree[maxn*4];
struct no{
ll m,v;
}s[4];
bool C(const no &a,const no &b){
return a.m<b.m;
}
void wh(int k){
s[0].m=tree[ls].ma,s[0].v=tree[ls].va;
s[1].m=tree[ls].mb,s[1].v=tree[ls].vb;
s[2].m=tree[rs].ma,s[2].v=tree[rs].va;
s[3].m=tree[rs].mb,s[3].v=tree[rs].vb;
sort(s,s+4,C);
ll n1=s[0].m,v1=s[0].v,n2=0,v2=0;
for(int i=1;i<4;i++){
if(s[i].m==n1)v1+=s[i].v;
else {
if(!n2)n2=s[i].m,v2=s[i].v;
else if(n2==s[i].m)v2+=s[i].v;
}
}
tree[k].ma=n1,tree[k].va=v1;
if(n1==inf)tree[k].mb=n1,tree[k].vb=0;
else tree[k].mb=n2,tree[k].vb=v2; }
void build(int k,int L,int R){
tree[k].l=L,tree[k].r=R;
if(L==R){
tree[k].ma=tree[k].mb=inf;
return;
}
int mid=tree[k].l+tree[k].r>>1;
build(k*2,L,mid);build(k*2+1,mid+1,R);
wh(k);
}
void up(int k,int v){
tree[k].ma+=v;tree[k].mb+=v;tree[k].bj+=v;
}
void down(int k){
if(tree[k].bj!=0){
up(k*2,tree[k].bj);up(k*2+1,tree[k].bj);
tree[k].bj=0;
}
}
void add(int k,int li,int ri,int v){
if(li>ri)return;
if(tree[k].l>=li&&tree[k].r<=ri){
up(k,v);return;
}
down(k);
int mid=tree[k].l+tree[k].r>>1;
if(li<=mid)add(k*2,li,ri,v);
if(ri>mid)add(k*2+1,li,ri,v);
wh(k);
}
void ch(int k,int pl)
{
if(tree[k].l==tree[k].r){
tree[k].ma=1;tree[k].va=1;return;
}
down(k);
int mid=tree[k].l+tree[k].r>>1;
if(pl<=mid)ch(k*2,pl);
else ch(k*2+1,pl);
wh(k);
}
int main()
{
cin>>n;
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);p[a[i]]=i;
}
build(1,1,n);
for(int i=1;i<=n;i++){
int x=p[i];
int l=a[x-1],r=a[x+1];
if(l>r)swap(l,r);
if(l>=i)
add(1,1,i-1,1);
if(r>=i&&l<i)
add(1,l+1,i-1,1);
if(r<i){
add(1,1,l,-1);add(1,r+1,i-1,1);
}
if(tree[1].ma<3)ans+=tree[1].va;
if(tree[1].mb<3)ans+=tree[1].vb;
ch(1,i); }
cout<<ans<<endl;
return 0;
}
/*
5
1 4 2 5 3
*/

区间(interval)的更多相关文章

  1. 牛客网 牛客小白月赛5 I.区间 (interval)-线段树 or 差分数组?

    牛客小白月赛5 I.区间 (interval) 休闲的时候写的,但是写的心情有点挫,都是完全版线段树,我的一个队友直接就水过去了,为啥我的就超内存呢??? 试了一晚上,找出来了,多初始化了add标记数 ...

  2. 区间(interval)

    [问题描述]给定 N 个区间, 要求选出若干个区间 A1, A2, A3... Am (m > 1), 使得:|A1∩A2∩A3...∩Am| * |A1∪A2∪A3...∪Am|最大.[输入格 ...

  3. 牛客小白月赛5 I 区间 (interval) 【前缀和】

    链接:https://www.nowcoder.com/acm/contest/135/I 题目描述 Apojacsleam喜欢数组. 他现在有一个n个元素的数组a,而他要对a[L]-a[R]进行M次 ...

  4. [LeetCode] Data Stream as Disjoint Intervals 分离区间的数据流

    Given a data stream input of non-negative integers a1, a2, ..., an, ..., summarize the numbers seen ...

  5. [LeetCode] 352. Data Stream as Disjoint Intervals 分离区间的数据流

    Given a data stream input of non-negative integers a1, a2, ..., an, ..., summarize the numbers seen ...

  6. Ceph源码解析:PG peering

    集群中的设备异常(异常OSD的添加删除操作),会导致PG的各个副本间出现数据的不一致现象,这时就需要进行数据的恢复,让所有的副本都达到一致的状态. 一.OSD的故障和处理办法: 1. OSD的故障种类 ...

  7. SQLserver 获取当前时间

    1. 获取当前日期 select GETDATE() 格式化: select CONVERT(varchar,GETDATE(),120) --2017-05-12 16:33:10 2. 获取当前年 ...

  8. echarts 技巧自己的一些记录

    1.不要输出 window["echarts"].init(chart) ,会卡死. let chart = document.getElementById("chart ...

  9. LeetCode: Merge Intervals 解题报告

    Merge IntervalsGiven a collection of intervals, merge all overlapping intervals. For example,Given [ ...

  10. sql获取时间、年龄

      mysql数据库获取年龄:TIMESTAMPDIFF(YEAR, [出生日期字段], CURDATE()) select * from (select name 姓名,TIMESTAMPDIFF( ...

随机推荐

  1. js延迟加载的方式有哪些?

    共有:defer和async.动态创建DOM方式(用得最多).按需异步载入js defer属性:(页面load后执行) HTML 4.01 为 <script>标签定义了 defer属性. ...

  2. yii自定义行为组件(简介版)

    yii2 给框架底层预定义事件自定义处理程序. 1. common\config\main.php  修改配置文件添加   'as behaviors' => 'backend\behavior ...

  3. 解决SecureCRT远程Linux遇到文件不能直接往CRT里直接拖入的问题

    不能拖入到CRT的第一个原因可能是Options-->Global Options-->Terminal中的Mouse下的Copy on select没有勾选.当发现自己勾选了也不能往里面 ...

  4. U盘装机记录

    U盘装机记录 1. 将U盘制作为启动盘(安装PE文件到U盘). (1)准备材料 8G以上U盘一个 一个可信的启动盘制作工具(这里是用的老毛桃) (2)将U盘插入电脑,单击老毛桃客户端(出现如下图所示的 ...

  5. acm总结

    注意事项: 不要轻易中途变换思路修改代码 发现有样例无法通过可以用if强行通过 注意输入输出形式(long long为lld,无符号为llu). 开过1亿的int型数组 Long long能读入输出1 ...

  6. 【UE4】二十三、UE4笔试面试题

    在CSDN博客看到的,带着这些问题,多多留意,正所谓带着问题学习. 一. 1.Actor的EndPlay事件在哪些时候会调用? 2.BlueprintImplementableEvent和Bluepr ...

  7. Python 外部函数调用库ctypes简介

    Table of Contents 1. 参考资料 2. ctypes简介 2.1. 数据类型 2.2. 调用.so/.dll 2.2.1. 加载动态链接库 2.2.2. 调用加载的函数 2.2.3. ...

  8. PHP.14-图片处理类

    图片处理类 test.php <?php include "images.class.php"; $image=new Image("./images/" ...

  9. 1096: [ZJOI2007]仓库建设

    1096: [ZJOI2007]仓库建设 思路 斜率优化. 代码 #include<cstdio> #include<iostream> using namespace std ...

  10. loadrunner检查点设置失败,日志中SaveCount无法被正常统计出来

    在脚本正确的情况下的web_reg_find检查点检查失败,SaveCount无法被正常统计出来. 在检查项Text为中文的情况下, ******(我是被录制下来的代码) web_reg_find(& ...