[51nod1810]连续区间
来源:互联网 发布:跆拳道教学软件 编辑:程序博客网 时间:2024/05/16 15:22
Description
给出一个1~n的排列,求有多少个区间将区间内所有元素排序后,任意相邻两个元素值差为1
n<=1e6
Solution
个人认为马拉松26中最可做的一道题(然而还是没有做出来
考虑分治,也就是我们要统计左端点在[l,mid],右端点在[mid+1,r]的区间个数
设max[i]表示i到mid的前缀/后缀max,min[i]表示i到mid的前缀/后缀min
设区间左端点为i,右端点为j,我们可以知道一个合法的区间必然满足
那么我们分4种情况讨论一下
若
那么
若
那么
这个区间可以线性维护,开个桶记录一下每个值出现的次数即可
后两种情况同理,那么总复杂度就是O(n log n)
Code
#include <cstdio>#include <cstring>#include <algorithm>#define fo(i,a,b) for(int i=a;i<=b;i++)#define fd(i,a,b) for(int i=a;i>=b;i--)using namespace std;typedef long long ll;const int N=1e6+5;int n,a[N],b[N*3],Max[N],Min[N];ll ans;int read() { char ch; for(ch=getchar();ch<'0'||ch>'9';ch=getchar()); int x=ch-'0'; for(ch=getchar();ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; return x;}void solve(int l,int r) { int mid=(l+r)/2; Max[mid]=Min[mid]=a[mid]; fd(i,mid-1,l) { Max[i]=max(a[i],Max[i+1]); Min[i]=min(a[i],Min[i+1]); } Max[mid+1]=Min[mid+1]=a[mid+1]; fo(i,mid+2,r) { Max[i]=max(a[i],Max[i-1]); Min[i]=min(a[i],Min[i-1]); } fd(i,mid,l) { int j=Max[i]-Min[i]+i; if (j>mid&&j<=r&&Max[i]>Max[j]&&Min[i]<Min[j]) ans++; } fo(j,mid+1,r) { int i=-(Max[j]-Min[j]-j); if (i>=l&&i<=mid&&Max[i]<Max[j]&&Min[i]>Min[j]) ans++; } int le=mid+1,ri=mid; fd(i,mid,l) { while (ri<r&&Max[ri+1]<Max[i]) ri++,b[Min[ri]+ri+N]++; while (le<=ri&&Min[le]>Min[i]) b[Min[le]+le+N]--,le++; ans+=b[Max[i]+i+N]; } while (le<=ri) b[Min[le]+le+N]--,le++; le=mid+1;ri=mid; fo(j,mid+1,r) { while (le>l&&Max[le-1]<Max[j]) le--,b[Min[le]-le+N]++; while (ri>=le&&Min[ri]>Min[j]) b[Min[ri]-ri+N]--,ri--; ans+=b[Max[j]-j+N]; } while (le<=ri) b[Min[ri]-ri+N]--,ri--; if (l==r) return; solve(l,mid);solve(mid+1,r);}int main() { n=read(); fo(i,1,n) a[i]=read(); solve(1,n); printf("%lld\n",ans+n);}
阅读全文
1 0
- [51nod1810]连续区间
- 【51Nod1810】连续区间
- 51Nod-1810-连续区间
- 51nod 1810 连续区间
- 51nod 1810 连续区间(分治)
- 连续区间最大值
- 蓝桥杯连续区间数
- 区间连续极值
- 效验连续区间
- 51nod 1393 0和1相等串 (连续区间)
- 51nod 1094 和为k的连续区间
- 51nod 1094 和为k的连续区间
- 51nod 1094 和为k的连续区间
- 51nod-1094 和为k的连续区间
- 51nod 1094 和为k的连续区间
- 51nod-【1094 和为k的连续区间】
- 51Nod 1094 和为k的连续区间
- 51nod 1094 和为k的连续区间
- python简单实现目录对比
- javascript /微信小程序中MD5加密
- 抽象类
- commons-fileupload组件上传图片介绍
- 提高网站(web应用)访问速度的几点建议(前端)
- [51nod1810]连续区间
- linux中的ethtool命令
- day_03 DayOff
- java笔记作业
- Caffe 特征图可视化
- 专题:强大的运算工具——矩阵
- C++派生类中如何初始化基类对象
- Python之列表应用
- SSM框架整合