original link - http://poj.org/problem?id=4005

题意:

有n个数,按照给出的顺序依次插入二叉搜索树,然后从小到大遍历(从根开始往下走,最后回来),路过的点值模2构成一个01序列 S S S,求这个序列中出现匹配串 T T T的次数。

解析:

可以分为两个问题:怎么构造出树的结构、怎么查询匹配串出现次数。


如果直接暴力查看是哪个点的儿子,一条链的情况下复杂度 O ( n 2 ) O(n^2) O(n2)。

开始的做法:

用set维护每个点的可以变为儿子的区间,插入时二分得到区间
\;
但是常数太大 T L E TLE TLE了。

后来发现了其中与笛卡尔树联系颇深,构造出来的树按序号看是小顶堆,按值看是二叉搜素树。
将其按照值排序后,再按照序号大小关系建笛卡尔树,就是正解了,时间复杂度 O ( n l o g n + n ) O(nlogn+n) O(nlogn+n)。


建好树后,得到字符串的过程,如果直接搜索会爆栈,改成栈模拟即可。

最后的过程比较简单,查看出现多少次,那么就是将 S , T → T S S,T\to TS S,T→TS,然后做一遍 Z A l g o r i t h m Z\;Algorithm ZAlgorithm,后面的每个位置匹配长度大于 ∣ T ∣ |T| ∣T∣就说明有一个。

代码:

/**  Author : Jk_Chen*    Date : 2019-10-05-12.07.13*/
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<iostream>
#include<algorithm>
#include<set>
#include<stack>
#include<stdlib.h>
using namespace std;
#define LL long long
#define rep(i,a,b) for(int i=(int)(a);i<=(int)(b);i++)
#define per(i,a,b) for(int i=(int)(a);i>=(int)(b);i--)
#define mmm(a,b) memset(a,b,sizeof(a))
#define pb push_back
#define pill pair<int, int>
#define fi first
#define se second
#define debug(x) cerr<<#x<<" = "<<x<<'\n';
const LL mod=1e9+7;
const int maxn=7e5+5;
const int inf=0x3f3f3f3f;
LL rd(){ LL ans=0; char last=' ',ch=getchar();while(!(ch>='0' && ch<='9'))last=ch,ch=getchar();while(ch>='0' && ch<='9')ans=ans*10+ch-'0',ch=getchar();if(last=='-')ans=-ans; return ans;
}
#define rd rd()
/*_________________________________________________________begin*/char x[maxn*5];
int len1,len;
int z[maxn*5];
void deal(){ // Z Algorithmmmm(z,0);int l=0,r=1;rep(i,1,len-1){if(r>i)z[i]=min(z[i-l],r-i);if(z[i]+i>=r){l=i,r=z[i]+i;while(r<len&&x[r]==x[r-l])r++;z[i]=r-l;}}z[0]=len;
}int son[maxn][2];
pill a[maxn];
bool vis[maxn];
int sta[maxn];
int rt;void init(int n){int top=0;rep(i,1,n){vis[i]=0;son[i][0]=son[i][1]=0;}rep(i,1,n){int lson=-1;while(top&&a[sta[top]].se>a[i].se)lson=sta[top],top--;if(top)son[sta[top]][1]=i;if(~lson)son[i][0]=lson;sta[++top]=i;}rep(i,1,n){vis[son[i][0]]=vis[son[i][1]]=1;}rep(i,1,n){if(!vis[i]){rt=i;break;}}
}void dfs(int p){stack<pill>S;S.push({p,1});while(!S.empty()){pill pi=S.top();S.pop();x[len++]='0'+pi.fi%2;if(pi.se){if(son[pi.fi][1]){S.push({pi.fi,0});S.push({son[pi.fi][1],1});}if(son[pi.fi][0]){S.push({pi.fi,0});S.push({son[pi.fi][0],1});}}}
}int main(){int t=rd,cas=0;while(t--){int n=rd;rep(i,1,n)a[i].fi=rd,a[i].se=i;sort(a+1,a+1+n);gets(x);len=len1=strlen(x);init(n);dfs(rt);x[len]='\0';
//        puts(x);deal();int ans=0;rep(i,len1,len-1){if(z[i]>=len1)ans++;}printf("Case #%d: %d\n",++cas,ans);}
}

Moles(笛卡尔树 Z Algorithm)相关推荐

  1. HDU 4125 Moles 笛卡尔树 + kmp

    题意:有n(1<=n<=600000)个鼹鼠挖洞,每个鼹鼠有给定权值,挖的洞是一颗二叉树(左边的鼹鼠权值都比当前鼹鼠小,右边的鼹鼠权值比当前鼹鼠大), 也要按照鼹鼠的出场顺序挖洞,在形成的 ...

  2. [线段树or笛卡尔树+简单KMP]poj4005 or hdu4125 Moles

    题意:N只编号1-N的鼹鼠打洞,第i只编号为a[i],编号不重复.打的洞的样子符合以a[i]为值,以下标为插入顺序的二叉搜索树.现在从根出发,存在左子树则先走左子树,否则往右走,每经过一个洞(结点), ...

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

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

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

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

  5. YbtOJ#20240-[冲刺NOIP2020模拟赛Day10]弱者对决【笛卡尔树,区间dp】

    正题 题目链接:https://www.ybtoj.com.cn/contest/68/problem/4 题目大意 mmm个三元组(ai,bi,ci)(a_i,b_i,c_i)(ai​,bi​,ci ...

  6. 【笛卡尔树】【线段树】meetings 会议(P5044)

    正题 P5044 题目大意 给出一个序列a,设 dist(x,y)=max⁡i=xyaidist(x,y)=\max_{i=x}^ya_idist(x,y)=maxi=xy​ai​,有m个询问,对于每 ...

  7. [BZOJ]4199: [Noi2015]品酒大会(后缀数组+笛卡尔树)

    Time Limit: 10 Sec  Memory Limit: 512 MB Description Input Output Sample Input 10 ponoiiipoi 2 1 4 7 ...

  8. HDU - 6305 RMQ Similar Sequence(笛卡尔树)

    http://acm.hdu.edu.cn/showproblem.php?pid=6305 题目 对于A,B两个序列,任意的l,r,如果RMQ(A,l,r)=RMQ(B,l,r),B序列里的数为[0 ...

  9. 洛谷 - P4755 Beautiful Pair(笛卡尔树+主席树)

    题目链接:点击查看 题目大意:给出一个长度为 n 的数列 a,现在一个数对 ( i , j ) 如果满足 a[ i ] * a[ j ] <=max( a[ i ] ~ a[ j ] ),则称其 ...

最新文章

  1. 零基础入门--中文命名实体识别(BiLSTM+CRF模型,含代码)
  2. mysql的突然变成本地不能用密码,远程要用密码才能登录,这是神马情况???求解...
  3. 5个酷毙的Python神器工具
  4. angular2 组件交互
  5. 洛谷 - P3391 【模板】文艺平衡树(Splay-区间反转)
  6. 表单验证JavaScript实现正则匹配、随机验证码、密码强度、加拖拽加蒙板
  7. 在cygwin下编译c语言
  8. python multiprocessing 得到多进程返回的结果
  9. linux查看后台执行的所有任务与对应的命令
  10. mysql——启动服务问题Found option without preceding group in config file
  11. 入门Python,看这一篇就够了,史上最全的Python基础语法知识清单!
  12. Linux命令----系统目录结构
  13. 身份证阅读器读卡器React网页方法实现身份证的读取
  14. svn版本管理软件——svn分支管理
  15. 命令行字符界面与图形界面切换
  16. 开发历程:网页视频流媒体播放器EasyPlayer.JS开发web H5网页播放H.265视频支持FLV与HLS直播与点播
  17. excel锁定第一行_将Excel标题行锁定在适当的位置
  18. python 二维码生成器_python二维码生成器
  19. 什么是localhost(127.0.0.1)?
  20. goaheadlinux移植_goahead(嵌入式Web服务器)之交叉编译、移植篇

热门文章

  1. 两轮电动车被小米、哈啰们盯上了
  2. 终极事务处理(XTP,Hekaton)——万能大招?
  3. FCFS和SJF算法
  4. Unity Shader 实现简单的压扁效果
  5. char **argv什么意思呢
  6. 数据可视化——彩色通用设计之色彩搭配(制作对色盲人群友好的图形和演示)
  7. Android 一个简单手机响铃功能实现
  8. 揭开深度跟踪的力量--Unveiling the Power of Deep Tracking (ECCV2018)
  9. [Linux Shell] su和sudo命令
  10. java joda datetime_关于java:使用Joda将日期转换为DateTime