CF1156E Special Segments of Permutation

思路:笛卡尔树?(好像并不一定要建出来,但是可以更好理解)

提交:2次

错因:没有判左右儿子是否为空来回溯导致它T了

题解:

建出笛卡尔树,考虑如何计算答案:
先预处理每一个值出现的位置 \(pos[]\);
对于每一个有左右儿子的点,设他在原序列中的值为 \(mx\),根据笛卡尔树的性质,他比自己的子树中的任何一个元素都大 。这样, 我们遍历他的轻儿子中的元素 \(vl\) ,查询 \(pos[mx-vl]\) 是否在重子树中。
其实可以不建树,直接求出每个点作为最大值能够向左右扩展的区间,枚举小的区间就够了。
复杂度 \(O(nlogn)\) ,原因是类似树剖,每个点最多只会向上跳 \(logn\) 条轻边;而一个点被计算,只有在枚举轻子树的时候;其实类似dsu on tree。
当然,不建树的做法的复杂度虽然解释不同,但本质都是一样的、

代码:

#include<bits/stdc++.h>
#define R register int
using namespace std;
namespace Luitaryi {
inline int g() { R x=0,f=1;
  register char ch; while(!isdigit(ch=getchar())) f=ch=='-'?-1:f;
  do x=x*10+(ch^48); while(isdigit(ch=getchar())); return x*f;
} const int N=250010;
int n,rt,a[N],pos[N],ans;
struct node {int ls,rs,sz,l,r;} t[N];
#define ls(tr) t[tr].ls
#define rs(tr) t[tr].rs
#define sz(tr) t[tr].sz
#define l(tr) t[tr].l
#define r(tr) t[tr].r
int stk[N],top;
inline void calc(int tr,int rn,int mx) {
  for(R i=l(tr);i<=r(tr);++i)
    ans+=(pos[mx-a[i]]>=l(rn)&&pos[mx-a[i]]<=r(rn));
}
inline void dfs(int tr) {
  sz(tr)=1,l(tr)=r(tr)=tr;
  if(ls(tr)) dfs(ls(tr)),l(tr)=l(ls(tr));
  if(rs(tr)) dfs(rs(tr)),r(tr)=r(rs(tr));
  if(!ls(tr)||!rs(tr)) return ;
  sz(tr)=sz(ls(tr))+sz(rs(tr));
  if(sz(ls(tr))<sz(rs(tr))) calc(ls(tr),rs(tr),a[tr]);
  else calc(rs(tr),ls(tr),a[tr]);
}
inline void main() {
  n=g(); for(R i=1;i<=n;++i) a[i]=g(),pos[a[i]]=i;
  stk[++top]=0,a[0]=1e9;
  for(R i=1;i<=n;++i) { R lst=0;
    while(a[stk[top]]<a[i]) lst=stk[top],--top;
    ls(i)=lst,rs(stk[top])=i; stk[++top]=i;
  } rt=stk[2];
  dfs(rt); printf("%d\n",ans);
}
} signed main() {Luitaryi::main(); return 0;}


2019.09.15
61

原文地址:https://www.cnblogs.com/Jackpei/p/11525095.html

时间: 2024-10-17 03:41:12

CF1156E Special Segments of Permutation的相关文章

CF1156E Special Segments of Permutation【题解】瞎搞 单调栈

题面:http://codeforces.com/contest/1156/problem/E Luogu翻译:https://www.luogu.com.cn/problem/CF1156E 话说Luogu要改域名了. 大意:给定一个长度为n的排列p,求有多少区间[l,r]满足,p[l]+p[r]=max{p[i]},其中l<=i<=r 据说可以笛卡尔树. 可是我不会. 那么就瞎搞. 预处理出左边第一个比a[i]大的数的位置,记为L[i] R[i]同理为右边. 这个可以用单调栈求. 然后就可

Educational Codeforces Round 64 (Rated for Div. 2)

题目链接:https://codeforces.com/contests/1156 A. Inscribed Figures 题目大意:假设1代表圆形,2代表正三角形,3代表正方形,那么如例一所示2 1 3就代表正三角形内接圆形,同时内接圆的内部再内接正方形.那么现在所需要求的就是通过不断内接图形最终有多少个交点,如果在这个过程中内接的图形与之有边重合则 Infinite 解题思路:分别画出1 2 3 .1 3 2.2 1 3.2 3 1.3 1 2.3 2 1,就可以得出规律如下 1中内接2或

【译】x86程序员手册18-6.3.1描述符保存保护参数

6.3 Segment-Level Protection 段级保护 All five aspects of protection apply to segment translation: 段转换时会提供以下5个方面的保护: Type checking 类型检验 Limit checking 限长检验 Restriction of addressable domain 可寻址域的限定 Restriction of procedure entry points 程序入口点的限定 Restricti

[LeetCode] Find Permutation 找全排列

By now, you are given a secret signature consisting of character 'D' and 'I'. 'D' represents a decreasing relationship between two numbers, 'I' represents an increasing relationship between two numbers. And our secret signature was constructed by a s

HDU5753 Permutation Bo(2016多校训练)

Permutation Bo Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 777    Accepted Submission(s): 468Special Judge Problem Description There are two sequences h1∼hn and c1∼cn . h1∼hn is a permutat

HNU Joke with permutation (深搜dfs)

题目链接:http://acm.hnu.cn/online/?action=problem&type=show&id=13341&courseid=0 Joke with permutation Time Limit: 3000ms, Special Time Limit:7500ms, Memory Limit:65536KB Total submit users: 85, Accepted users: 57 Problem 13341 : Special judge Prob

hdu 5753 Permutation Bo

这里是一个比较简单的问题:考虑每个数对和的贡献.先考虑数列两端的值,两端的摆放的值总计有2种,比如左端:0,大,小:0,小,大:有1/2的贡献度.右端同理. 中间的书总计有6种可能.小,中,大.其中有两种对答案有贡献,即1/3的贡献度.加和计算可得到答案. Permutation Bo Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)Total Submission(s):

ZOJ3349——Special Subsequence

Special Subsequence Time Limit: 5 Seconds      Memory Limit: 32768 KB There a sequence S with n integers , and A is a special subsequence thatsatisfies |Ai-Ai-1| <= d ( 0 <i<=|A|)) Now your task is to find the longest special subsequence of a cer

POJ 1436 Horizontally Visible Segments(线段树)

POJ 1436 Horizontally Visible Segments 题目链接 线段树处理染色问题,把线段排序,从左往右扫描处理出每个线段能看到的右边的线段,然后利用bitset维护枚举两个线段,找出另一个两个都有的线段 代码: #include <cstdio> #include <cstring> #include <algorithm> #include <bitset> #include <vector> using namesp