题意:N只编号1-N的鼹鼠打洞,第i只编号为a[i],编号不重复。打的洞的样子符合以a[i]为值,以下标为插入顺序的二叉搜索树。现在从根出发,存在左子树则先走左子树,否则往右走,每经过一个洞(结点),如果这个洞的值是奇数,就记录1,否则记录0,得到的dfs序列是01串S。注意是dfs序列不是中序遍历得到的序列,每个点最多被经过3次:root->lson...lson->root->rson...rson->root.

给定一个串T,问T在S中出现多少次。

求出S之后KMP就好惹。

关键:某个点a[i]的父亲是 左边的数中 比它小的数中最大的值L 或者 比它大的数的最小值R。

L和R都不存在,a[i]是根

仅L不存在,a[i]是R的左儿子

仅R不存在,a[i]是L的右儿子

都存在则L的右儿子和R的左儿子必有一个为空,a[i]就放在空的那个地方。
可以用set求L,R,但是我写会T;  
线段树求L,R+读入挂  2938ms/3000ms  ,不加会T
笛卡尔树1719ms

笛卡尔树看结点的key满足二叉搜索树,看结点的value满足堆(按具体实现分为小顶堆or大顶堆,此题小顶堆)
a[i]为key,i为value,则value满足早点到的一定最浅,key满足二叉搜索树。  
S,T匹配用kmp;注意这个二叉搜索树可能是一条链,dfs序列递归求可能会爆栈,用栈模拟即可√。

线段树:

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <map>
using namespace std;
const int maxn=6e5+5;
int t,n,stop,a[maxn];
char S[maxn*5],T[7005];
int L[maxn<<2],R[maxn<<2];
int stk[maxn],top;
#define lson (t<<1)
#define rson (t<<1|1)
void build(int t,int l,int r){if(l==r){L[t]=-1;R[t]=1e9;return;}int mid=l+r>>1;build(lson,l,mid);build(rson,mid+1,r);L[t]=-1;R[t]=1e9;
}
void update(int t,int l,int r,int pos){if(l==r){L[t]=R[t]=l;return;}int mid=l+r>>1;if(pos<=mid) update(lson,l,mid,pos);else update(rson,mid+1,r,pos);L[t]=max(L[lson],L[rson]);R[t]=min(R[lson],R[rson]);
}
int queryL(int t,int l,int r,int pos){if(r<=pos) return L[t];int mid=l+r>>1;if(pos<=mid) return queryL(lson,l,mid,pos);else return max(L[lson],queryL(rson,mid+1,r,pos));
}
int queryR(int t,int l,int r,int pos){if(l>=pos) return R[t];int mid=l+r>>1;if(pos<=mid) return min(queryR(lson,l,mid,pos),R[rson]);else return queryR(rson,mid+1,r,pos);
}
int lchild[maxn],rchild[maxn],fa[maxn];
void dfs(int u){stk[top++]=u;while(top){int u=stk[top-1];S[stop++]=(u&1)?'1':'0';if(lchild[u]){stk[top++]=lchild[u];lchild[u]=0;}else if(rchild[u]){stk[top++]=rchild[u];rchild[u]=0;}else{top--;}}S[stop]='\0';
}
int nt[7000+5];
char b[10001];
//参数为模板串和next数组
//字符串均从下标0开始
//参数为模板串和next数组
//字符串均从下标0开始
void kmp_next()
{nt[0]=0;for(int i=1,j=0,m=strlen(T);i<m;i++){while(j&&T[i]!=T[j])j=nt[j-1];if(T[i]==T[j])j++;nt[i]=j;}
}
int kmp()
{kmp_next();int ans=0,sn=strlen(S),tn=strlen(T);for(int i=0,j=0;i<sn;i++){while(j&&S[i]!=T[j])j=nt[j-1];if(S[i]==T[j])j++;if(j==tn)ans++;}return ans;
}
inline char nc() {static char buf[100000], *p1 = buf, *p2 = buf;return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 100000, stdin), p1 == p2) ? EOF : *p1++;
}inline int _read() {char ch = nc(); int sum = 0;while (!(ch >= '0'&&ch <= '9'))ch = nc();while (ch >= '0'&&ch <= '9')sum = sum * 10 + ch - 48, ch = nc();return sum;
}
inline void  _sread(){char ch = nc();int p=0;while (!(ch >= '0'&&ch <= '9'))ch = nc();while (ch >= '0'&&ch <= '9')T[p++] =ch, ch = nc();T[p]='\0';
}
int main()
{t=_read();int kase=0;while(t--){n=_read();int root=-1;stop=0;build(1,1,n);for(int i=1;i<=n;i++) lchild[i]=0,rchild[i]=0;for(int i=1;i<=n;i++){a[i]=_read();int l=queryL(1,1,n,a[i]),r=queryR(1,1,n,a[i]);if(l==-1&&r==1e9) root=a[i];else if(l==-1){lchild[r]=a[i];fa[a[i]]=r;}else if(r==1e9){rchild[l]=a[i];fa[a[i]]=l;}else{if(!lchild[r]) lchild[r]=a[i],fa[a[i]]=r;else rchild[l]=a[i],fa[a[i]]=l;}update(1,1,n,a[i]);}_sread();stop=0;dfs(root);//   printf("S=%s\n",S);int ans=kmp();printf("Case #%d: %d\n",++kase,ans);}return 0;
}

笛卡尔树:

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <map>
using namespace std;
const int N=6e5+5;
int t,n,x;int fa[N],ls[N],rs[N];
int stk[N],top,stop;
char S[N*5],T[7005];
void dfs(int u){stk[top++]=u;while(top){int u=stk[top-1];S[stop++]=(u&1)?'1':'0';if(ls[u]){stk[top++]=ls[u];ls[u]=0;}else if(rs[u]){stk[top++]=rs[u];rs[u]=0;}else{top--;}}S[stop]='\0';
}
int nt[7000+5];
char b[10001];
//参数为模板串和next数组
//字符串均从下标0开始
//参数为模板串和next数组
//字符串均从下标0开始
void kmp_next()
{nt[0]=0;for(int i=1,j=0,m=strlen(T);i<m;i++){while(j&&T[i]!=T[j])j=nt[j-1];if(T[i]==T[j])j++;nt[i]=j;}
}
int kmp()
{kmp_next();int ans=0,sn=strlen(S),tn=strlen(T);for(int i=0,j=0;i<sn;i++){while(j&&S[i]!=T[j])j=nt[j-1];if(S[i]==T[j])j++;if(j==tn)ans++;}return ans;
}
int root;
struct node{int id,v;bool operator < (const node &b)const{return v<b.v;}
}e[N];
int main(){scanf("%d",&t);int kase=0;while(t--){stop=top=0;scanf("%d",&n);for(int i=1;i<=n;i++) scanf("%d",&e[i].v),e[i].id=i;memset(ls,0,sizeof(ls));memset(rs,0,sizeof(rs));memset(fa,0,sizeof(fa));sort(e+1,e+n+1);stk[0]=0;for(int i = 1; i <= n; i ++){while(top && e[stk[top]].id > e[i].id)ls[i] = stk[top], top --;fa[i] = stk[top];fa[ls[i]] = i;if(fa[i]){rs[fa[i]] = i;}else{root=i;}stk[++ top] = i;}scanf("%s",T);stop=top=0;dfs(root);//  printf("%s\n",S);int ans=kmp();printf("Case #%d: %d\n",++kase,ans);root=0;}return 0;
}

[线段树or笛卡尔树+简单KMP]poj4005 or hdu4125 Moles相关推荐

  1. 笛卡尔树 (25 分)笛卡尔树是一种特殊的二叉树,其结点包含两个关键字K1和K2。首先笛卡尔树是关于K1的二叉搜索树,即结点左子树的所有K1值都比该结点的K1值小,右子树则大。其次所有结点的K2关键字

    立志用最少的代码做最高效的表达 笛卡尔树是一种特殊的二叉树,其结点包含两个关键字K1和K2.首先笛卡尔树是关于K1的二叉搜索树,即结点左子树的所有K1值都比该结点的K1值小,右子树则大.其次所有结点的 ...

  2. 笛卡尔树详解带建树模板及例题运用(Largest Submatrix of All 1’s,洗车 Myjnie,Removing Blocks,SPOJ PERIODNI)

    文章目录 笛卡尔树 介绍 例题 Largest Submatrix of All 1's 应用 「POI2015」洗车 Myjnie [AGC028B] Removing Blocks SPOJ PE ...

  3. [BZOJ]5042: LWD的分科岛 笛卡尔树+LCA

    Description 大家都知道在文理分科的时候总是让人纠结的,纠结的当然不只是自己.比如 YSY 就去读了文科, LWD 知道了很气.于是他就去卡了 BZOJ 测评机, 晚上他做了一个谜一样的梦, ...

  4. 7-31 笛卡尔树 (25 分)

    7-31 笛卡尔树 (25 分) 笛卡尔树是一种特殊的二叉树,其结点包含两个关键字K1和K2.首先笛卡尔树是关于K1的二叉搜索树,即结点左子树的所有K1值都比该结点的K1值小,右子树则大.其次所有结点 ...

  5. [算法学习] 线段树,树状数组,数堆,笛卡尔树

    都是树的变种,用途不同 [线段树 Interval Tree] 区间管理,是一种平衡树 可看做是对一维数组的索引进行管理.一维数组不需要是排序好的 深度不超过logL 任一个区间(线段)都分成不超过2 ...

  6. 牛客 - sequence(笛卡尔树+线段树)

    题目链接:点击查看 题目大意:给出一个长度为 n 的数列 a 和数列 b ,求 题目分析:不算难的题目,对于每个 a[ i ] 求一下贡献然后维护最大值就好,具体思路就是,先找出每个 a[ i ] 左 ...

  7. 【IOI2018】会议【笛卡尔树】【dp】【线段树】

    题意:长度为nnn的序列,qqq次询问,每次给定一个区间,钦定区间中的一个位置xxx,使得区间所有点 与xxx之间的最大值(含端点) 之和 最小,输出最小值. n,q≤7.5×105n,q\leq7. ...

  8. YbtOJ#752-最优分组【笛卡尔树,线段树】

    正题 题目链接:http://www.ybtoj.com.cn/problem/752 题目大意 nnn个人,每个人有cic_ici​和did_idi​分别表示这个人所在的队伍的最少/最多人数. 然后 ...

  9. P4755-Beautiful Pair【笛卡尔树,线段树】

    正题 题目链接:https://www.luogu.com.cn/problem/P4755 题目大意 nnn个数字的一个序列,求有多少个点对i,ji,ji,j满足ai×aj≤max{ak}(k∈[l ...

最新文章

  1. R构建指数回归模型(Exponential Regression)
  2. UVA - 10615 Rooks
  3. VTK:Utilities之3DArray
  4. cocos2d-x初探学习笔记(11)--拖动间隐效果
  5. FastReport v3.2.5在BDS2006中的安装方法
  6. 字典,和字典的增删改查
  7. 基于物理着色(二)- Microfacet材质和多层材质
  8. java jobdetail_Spring创建JobDetail的两种方式
  9. vue 同一个页面路由无反应_vue参数不同但是跳转同一个路由页面,及name的作用...
  10. NYOJ--1A+B Problem(练手题)
  11. 电阻电容等常见元器件的封装介绍
  12. Aiml中文包含英文(字母,特殊符号)识别问题的解决
  13. i79750h和i511400h哪个好
  14. html5中图像水平边距,图像的垂直边距和水平边距属性
  15. 智能投顾-用户画像、投资组合选择、推荐引擎、大数据挖掘
  16. c语言最简单的程序流程图,高手帮忙画个流程图简单的俄罗斯方块C语言程 – 手机爱问...
  17. 《经济学通识》八、劳动关系
  18. MFC编辑框数据读写
  19. Windows下的ARP命令
  20. C++ 快速傅里叶变换

热门文章

  1. ubuntuv20启动界面美化_玩转Reno4手机,ColorOS 7.2界面清爽更贴心_手机通讯
  2. iOS 获取手机的ip地址 并传给后台(三步搞定)
  3. CS5261|CS5265|Type-C转HDMI 4K30HZ 4K60HZ音视频
  4. 语音芯片排行榜,为何唯创知音WT588F语音芯片如此受欢迎
  5. 采用Eclipse为IDE,设计一个Java程序,实现根据指定年份、月份计算该月天数的功能,即程序输入为年、月,输出为该月的天数。
  6. html添加微信号,html代码点击复制微信号并自动打开微信添加好友
  7. 【U盘主控芯片的优缺点】
  8. 终于被我搞掂了 Vue3 + Element 的正确打开方式(直接拿来就用)
  9. centos7 teamspeak3的搭建
  10. 浅析Js中${}字符串拼接