题目链接:https://codeforc.es/contest/1156/problem/E

题目大意:

在数组p中可以找到多少个不同的l,r满足

思路:

ST表+并查集。

ST表还是需要的,因为nlongn的预处理就可以O(1)查询。枚举所有的区间也就O(n^2)。

因为是输入固定1-n,所以我可以设一个y数组表示数组p的值所对应的下标。

(习惯输入为x数组)

我们考虑一个区间[l,r]这个区间最大值为i。(这里用ST表可以找到)

[l,r]对答案的贡献为最大值i左边找一个值a,右边找一个值b,满足a+b==i。有多少个不同的a,b对。

我们可以枚举i左右两边长度小的区间。然后在大区间上找。(小区间就可以少枚举点不是吗?最坏左右区间长度一样总共也就nlongn次)。

然后的问题是怎样找快速查找。

我们用并查集。

把大区间的所有值加入在大区间的最大值上。

你一定疑惑这样做还是会超时的啊。

如果在我们得到这个区间对答案的贡献后,把i左右两区间的最大值加在i上就可以完美的解决这个问题了。

我们直接从区间[1,n]开始,向下遍历,稍微注意一下边缘条件就OK啦。

整个就像一个线段树呢。

人太垃圾,ST表直接复制的板子,如有抄袭希望可以交个朋友哈~~

#include<bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(false);
#define int long long
#define N 200100
#define mod 1000000007 int x[N];
int y[N]; int pre[N];
int find(int x)
{
int r=x;
while(pre[r]!=r)
r=pre[r];
int i=x,j;
while(i!=r)
{
j=pre[i];
pre[i]=r;
i=j;
}
return r;
}
void join(int x,int y)
{
int a=find(x);
int b=find(y);
if(a!=b)
{
pre[a]=b;
}
}
void into()
{
for(int i=; i<N; i++)
{
pre[i]=i;
}
} int st[N][]; void init(int n)
{
n++;
for (int i = ; i < n; i++)
st[i][] = x[i]; for (int j = ; ( << j) <= n; j++)
{
for (int i = ; i + ( << j) - < n; i++)
st[i][j] = max(st[i][j - ],st[i + ( << (j - ))][j - ]);
}
} int search(int l, int r)
{
int k = (int)(log((double)(r - l + )) / log(2.0));
return max(st[l][k],st[r - ( << k) + ][k]);
} int Ans;
void dfs(int i,int l,int r)
{
int a=,b=;
if(y[i]>l)
{
a=search(l,y[i]-);
//cout<<i<<" "<<a<<endl;
dfs(a,l,y[i]-);
}
if(y[i]<r)
{
b=search(y[i]+,r);
//cout<<i<<" "<<b<<endl;
dfs(b,y[i]+,r);
} if(r-y[i]<y[i]-l)
{
for(int j=y[i]+; j<=r; j++)
{
if(find(i-x[j])==a)
{
Ans++;
}
}
}
else
{
for(int j=l; j<=y[i]-; j++)
{
if(find(i-x[j])==b)
{
Ans++;
}
}
}
if(a)
join(a,i);
if(b)
join(b,i);
} signed main()
{
IOS;
into(); int n,a;
cin>>n; for(int i=; i<=n; i++)
{
cin>>x[i];
y[x[i]]=i;
} init(n); dfs(n,,n); cout<<Ans; return ;
}

codeforces 1156E Special Segments of Permutation的更多相关文章

  1. Codeforces 1156E Special Segments of Permutation(单调栈)

    可以用单调栈直接维护出ai所能覆盖到的最大的左右范围是什么,然后我们可以用这个范围暴力的去查询这个区间的是否有满足的点对,一个小坑点,要对左右区间的大小进行判断,只需要去枚举距离i最近的一段区间去枚举 ...

  2. Codeforces 1156E Special Segments of Permutation(启发式合并)

    题意: 给一个n的排列,求满足a[l]+a[r]=max(l,r)的(l,r)对数,max(l,r)指的是l到r之间的最大a[p] n<=2e5 思路: 先用单调栈处理出每个点能扩展的l[i], ...

  3. Special Segments of Permutation - CodeForces - 1156E (笛卡尔树上的启发式合并)

    题意 给定一个全排列\(a\). 定义子区间\([l,r]\),当且仅当\(a_l + a_r = Max[l,r]\). 求\(a\)序列中子区间的个数. 题解 笛卡尔树上的启发式合并. \(200 ...

  4. CF1156E Special Segments of Permutation

    思路:笛卡尔树?(好像并不一定要建出来,但是可以更好理解) 提交:2次 错因:没有判左右儿子是否为空来回溯导致它T了 题解: 建出笛卡尔树,考虑如何计算答案: 先预处理每一个值出现的位置 \(pos[ ...

  5. codeforces 895B XK Segments 二分 思维

    codeforces 895B XK Segments 题目大意: 寻找符合要求的\((i,j)\)对,有:\[a_i \le a_j \] 同时存在\(k\),且\(k\)能够被\(x\)整除,\( ...

  6. Codeforces 785 E. Anton and Permutation(分块,树状数组)

    Codeforces 785 E. Anton and Permutation 题目大意:给出n,q.n代表有一个元素从1到n的数组(对应索引1~n),q表示有q个查询.每次查询给出两个数l,r,要求 ...

  7. CodeForces 219B Special Offer! Super Price 999 Bourles!

    Special Offer! Super Price 999 Bourles! Time Limit:1000MS     Memory Limit:262144KB     64bit IO For ...

  8. CodeForces 691D:Swaps in Permutation(并查集)

    http://codeforces.com/contest/691/problem/D D. Swaps in Permutation   You are given a permutation of ...

  9. codeforces 676A A. Nicholas and Permutation(水题)

    题目链接: A. Nicholas and Permutation time limit per test 1 second memory limit per test 256 megabytes i ...

随机推荐

  1. 可持久化BCJ

    BZOJ3674:可持久化并查集加强版 n个集合 m个操作操作:1 a b 合并a,b所在集合2 k 回到第k次操作之后的状态(查询算作操作)3 a b 询问a,b是否属于同一集合,是则输出1否则输出 ...

  2. Berlekamp-Massey algorithm

    https://www.cnblogs.com/zzqsblog/p/6877339.html https://blog.csdn.net/qq_39972971/article/details/80 ...

  3. Vue文件路径引入

  4. 【NOIP2016提高组day1】†换教室

    题目 对于刚上大学的牛牛来说,他面临的第一个问题是如何根据实际情况申请合适的 课程. 在可以选择的课程中,有 2n 节课程安排在 n 个时间段上. 在第 i ( 1 ≤ i ≤ n )个 时间段上,两 ...

  5. 正则化方法L1 L2

    转载:http://blog.csdn.net/u012162613/article/details/44261657(请移步原文) 正则化方法:防止过拟合,提高泛化能力 在训练数据不够多时,或者ov ...

  6. c# B/S下 如何优化文件上传速度和实现断点续传问题

    IE的自带下载功能中没有断点续传功能,要实现断点续传功能,需要用到HTTP协议中鲜为人知的几个响应头和请求头. 一. 两个必要响应头Accept-Ranges.ETag 客户端每次提交下载请求时,服务 ...

  7. pwd命令学习

    pwd命令学习 1.学习pwd命令 pwd命令功能为输出当前所在工作目录的绝对路径名称. 绝对路径和相对路径: 绝对路径:从根目录开始直到文件位置 相对路径:相对于程序当前所在目录到文件位置 例:程序 ...

  8. iOS 自定义一对UI表现相反的按钮

    假如有一对按钮[重置][提交],要让他们的默认UI和点击的UI表现刚好相反 [提交]按钮,默认橙色,点击边框是橙色,字体是橙色,背景变白色 [重置]按钮,默认白色橙色,边框是橙色,点击字体是白色,背景 ...

  9. CentOS7服务器配置

    CentOS7服务器配置 1.更换yum软件源 下载阿里源 cd /etc/yum.repos.d sudo wget -nc http://mirrors.aliyun.com/repo/Cento ...

  10. legend3---Windows 7/8/10 系统下Laravel框架的开发环境安装及部署详解(Vagrant + Homestead)

    legend3---Windows 7/8/10 系统下Laravel框架的开发环境安装及部署详解(Vagrant + Homestead) 一.总结 一句话总结: 1.安装的话就是下载好git,va ...