http://codeforces.com/contest/193/problem/D

题意:

给一个1~n的排列,在这个排列中选出两段区间,求使选出的元素排序后构成公差为1的等差数列的方案数。

换个角度思考问题,题意转化为存在多少对[L,R] ,(R>L),满足将值为[L,R]的区间染色后,所得区间数<=2

假设现在已知[L,R]的染色情况,看将值为L-1的位置染色后,区间数量的变化

若L-1左右两边都没有染色,区间数量+1

若L-1左右两边有一边染了色,区间数量不变

若L-1左右两边都染色了,区间数量-1

这样就有了枚举L R 的 n^2 做法

令f[i]表示当左端点为L,有端点为i时区间的数量

从大到小枚举L

考虑由[L,m]   m∈[L+1,n]  到 [L-1,m]  m∈[L,n] 时

f[i] i∈[L-1,n]的变化

设L-1 左右两边的数分别为x和y,且x<y

A、L-1左右两边都没有染色,即x<y<L-1,

染上L-1后会使区间数+1,即f[i]加1 ,i∈[L-1,n]

B、L-1左右两边有一边染色,即x<L-1<y,(y的那一边染色)

若染色的区间原本不包含y,染上L-1后会使区间数+1,即f[i]加1,i∈[L-1,y-1]

若染色的区间原本包含y,L-1与y相连,染上L-1后区间数不变

C、L-1左右两边都染色了,即L-1<x<y

若染色的区间原本不包含x,也不包含y,染上L-1后会使区间数+1,即f[i]加1,i∈[L-1,x-1]

若染色的区间原本只包含其中一个(只包含y),染山L-1后区间数不变

若染色的区间原本包含x和y,染上L-1后,两边的区间相连,区间数-1,即f[i]减1,i∈[y,n]

用线段树维护f[i]

这就变成了线段树的区间+1,区间-1,查询区间内f[i]<=2的数的个数

维护区间最小值mi[i],等于最小值的个数tot[i],等于最小值+1的个数tot1[i]

答案由两部分组成:

1、mi[i]<=2,ans+=tot[i]

2、mi[i]==1,ans+=tot1[i]

#include<cstdio>
#include<iostream>
#include<algorithm> using namespace std; #define N 300001 int a[N+],b[N+]; int tag[N<<];
int tot[N<<],tot1[N<<];
int mi[N<<]; long long ans=; void read(int &x)
{
x=; char c=getchar();
while(!isdigit(c)) c=getchar();
while(isdigit(c)) { x=x*+c-''; c=getchar(); }
} void build(int k,int l,int r)
{
tot[k]=r-l+;
if(l==r) return;
int mid=l+r>>;
build(k<<,l,mid);
build(k<<|,mid+,r);
} void down(int k)
{
tag[k<<]+=tag[k];
tag[k<<|]+=tag[k];
mi[k<<]+=tag[k];
mi[k<<|]+=tag[k];
tag[k]=;
} void update(int k)
{
mi[k]=min(mi[k<<],mi[k<<|]);
tot[k]=tot[k<<]*(mi[k<<]==mi[k])+tot[k<<|]*(mi[k<<|]==mi[k]);
tot1[k]=tot1[k<<]*(mi[k<<]==mi[k])+tot1[k<<|]*(mi[k<<|]==mi[k]);
tot1[k]+=tot[k<<]*(mi[k<<]==mi[k]+)+tot[k<<|]*(mi[k<<|]==mi[k]+);
} void change(int k,int l,int r,int opl,int opr,int w)
{
if(l>=opl && r<=opr)
{
mi[k]+=w;
tag[k]+=w;
return;
}
if(tag[k]) down(k);
int mid=l+r>>;
if(opl<=mid) change(k<<,l,mid,opl,opr,w);
if(opr>mid) change(k<<|,mid+,r,opl,opr,w);
update(k);
} void query(int k,int l,int r,int opl,int opr)
{
if(l>=opl && r<=opr)
{
ans+=tot[k]*(mi[k]<=)+tot1[k]*(mi[k]==);
return;
}
if(tag[k]) down(k);
int mid=l+r>>;
if(opl<=mid) query(k<<,l,mid,opl,opr);
if(opr>mid) query(k<<|,mid+,r,opl,opr);
} int main()
{
int n,m;
read(n);
int x,y;
for(int i=;i<=n;++i) read(x),a[x]=i;
build(,,n);
for(int i=n;i;--i)
{
b[a[i]]=i;
x=b[a[i]-];
y=b[a[i]+];
if(x>y) swap(x,y);
if(x)
{
change(,,n,y,n,-);
change(,,n,i,x-,);
}
else if(y) change(,,n,i,y-,);
else change(,,n,i,n,);
//long long last=ans;
query(,,n,i,n);
//cout<<i<<' '<<ans-last<<'\n';
}
cout<<ans-n;
}

Codeforces 193 D. Two Segments的更多相关文章

  1. Codeforces 1108E2 Array and Segments (Hard version) 差分, 暴力

    Codeforces 1108E2 E2. Array and Segments (Hard version) Description: The only difference between eas ...

  2. Codeforces 1108E2 Array and Segments (Hard version)(差分+思维)

    题目链接:Array and Segments (Hard version) 题意:给定一个长度为n的序列,m个区间,从m个区间内选择一些区间内的数都减一,使得整个序列的最大值减最小值最大. 题解:利 ...

  3. Codeforces 895.B XK Segments

    B. XK Segments time limit per test 1 second memory limit per test 256 megabytes input standard input ...

  4. 【CodeForces】899 E. Segments Removal

    [题目]E. Segments Removal [题意]给定n个数字,每次操作删除最长的连续相同数字(等长删最左),求全部删完的最少次数.n<=2*10^6,1<=ai<=10^9. ...

  5. 『ACM C++』 Codeforces | 1066A - Points in Segments

    大一生活真 特么 ”丰富多彩“ ,多彩到我要忙到哭泣,身为班长,很多班级的事情需要管理,也是,什么东西都得体验学一学,从学生会主席.团委团总支.社团社长都体验过一番了,现在差个班长也没试过,就来体验了 ...

  6. codeforces 652D D. Nested Segments(离散化+sort+树状数组)

    题目链接: D. Nested Segments time limit per test 2 seconds memory limit per test 256 megabytes input sta ...

  7. Codeforces 620F Xors on Segments(暴力+DP)

    题目链接 Xors on Segments 预处理出$x[i]$ $=$ $1$ $xor$ $2$ $xor$ $3$ $xor$ $……$ $xor$ $i$ 话说这题$O(n^{2})$居然能过 ...

  8. codeforces#1108E2. Array and Segments (线段树+扫描线)

    题目链接: http://codeforces.com/contest/1108/problem/E2 题意: 给出$n$个数和$m$个操作 每个操作是下标为$l$到$r$的数减一 选出某些操作,使$ ...

  9. Codeforces 429E - Points and Segments(欧拉回路)

    Codeforces 题面传送门 & 洛谷题面传送门 果然我不具备融会贯通的能力/ll 看到这样的设问我们可以很自然地联想到这道题,具体来说我们可以通过某种方式建出一张图,然后根据" ...

随机推荐

  1. 【BZOJ3529】数表(莫比乌斯反演,树状数组)

    [BZOJ3529]数表(莫比乌斯反演,树状数组) 题解 首先不管\(A\)的范围的限制 要求的东西是 \[\sum_{i=1}^n\sum_{j=1}^m\sigma(gcd(i,j))\] 其中\ ...

  2. 【HDU1754】I hate it!

    题面 很多学校流行一种比较的习惯.老师们很喜欢询问,从某某到某某当中,分数最高的是多少. 这让很多学生很反感. 不管你喜不喜欢,现在需要你做的是,就是按照老师的要求,写一个程序,模拟老师的询问.当然, ...

  3. [HDU5799]This world need more Zhu

    题面戳我 题意: 给定一棵树,m次操作,每次询问某一棵子树中,或者是某一条路径上,出现次数为a的所有数字之和与出现次数为b的所有数字之和的gcd 原题表述:the \(\gcd\) of the su ...

  4. 什么是Docker??

    ​​Docker是一个轻量级虚拟机,也是一种Linux容器,它突破了以往的沙盒技术,解放了应用部署,让PaaS的应用场景更为广泛. ​ docker是通过内核虚拟化技术((namespaces及cgr ...

  5. ajax错误处理 500错误

    在使用ajax请求的时候 ,如果服务器返回的是500错误,或者其他非正常的http错误状态码时 会提示下面的错误  而我们需要把错误信息处理出来 $.ajax({ type:'get', url:&q ...

  6. highcharts使用-拼接数据

    在写后台统计时,使用highcharts 作为数据视图化的工具 PHP端 拼接数据 1 首先分组查询出来数据 2 然后拼接出来想要的数据格式 $c_x ='';foreach ($courierGro ...

  7. Openstack Pycharm 的远程调试

    问题背景 最近再研究openstack cinder api的时候遇到了个问题:使用命令行调用API的时候,使用domain的token时,会产生一个错误,但是通过cinder的api都无法确定产生错 ...

  8. Java的string学习笔记 与char数组和bufferstring的比较

    ---恢复内容开始--- 一直用的C 导致这种类望而生畏 现在终于鼓起勇气学习一下 首先学习string类型 String s1 = "AbCdEf"; String s2 = & ...

  9. 13.C++-静态成员变量、静态成员函数

    首先回顾下成员变量 能通过对象名能够访问public成员变量 每个对象的成员变量都是专属的 成员变量不能在对象之间共享 再来讲讲类的静态成员变量 介绍 静态成员变量属于整个类所有 静态成员变量的生命期 ...

  10. C#压缩文件夹坑~

    dotNet疯狂之路No.29  今天很残酷,明天更残酷,后天很美好,但是绝大部分人是死在明天晚上,只有那些真正的英雄才能见到后天的太阳.  We're here to put a dent in t ...