NOIP模拟 Board
来源:互联网 发布:录入查询系统源码 编辑:程序博客网 时间:2024/06/06 15:46
给出这样一棵“二叉树”:
每个节点有左右两个儿子,并如下定义每个节点的高度:假设父亲节点的高度为 h ,那么他的两个儿子的节点的高度都是 h + 1 ,相同高度的所有节点称作一层。
每个节点的左儿子的子树都在右儿子的子树的左边,每一层相邻的两个节点之间有一条边。
下面是一个例子:
每一条图上的路径用一个字符串表示,字符串中的每一个字符表示一个移动。字符仅包含如下五种:
1:表示移动到当前节点的左儿子
2:表示移动到当前节点的右儿子
U:表示移动到当前节点的父亲节点
L:表示移动到当前节点同层的左边的节点(保证当前节点在这一层中不是最左边的节点)
R:表示移动到当前节点同层的右边的节点(保证当前节点在这一层中不是最右边的节点)
用一条路径来表示这条路径的终点,例如路径:221LU 就表示上图中的节点 A 。
给出两条路径,你的任务是求出着两条路径的终点之间的最短路。
输入格式
输入两行,每行一个字符串,分别表示两条路径。
输出格式
输出一行一个整数,表示能得到的串的总数。
样例数据 1
输入 [复制]
221LU
12L2
输出
3
备注
【数据规模与约定】
用 D 表示所有经过的节点中,深度最大的节点的深度;S 表示输入字符串的最大长度。
对于 10% 的数据,D≤10。
对于 30% 的数据,D≤50。
对于 50% 的数据,D≤1000。
对于 70% 的数据,D≤20000。
对于 100% 的数据,D≤100000;S≤100000。
解题思路
当确定了两个节点后,最短路就一定是两个节点向上移动到同一高度,然后再沿着这一层中间的边走过去,那么只要从根节点枚举这两个节点向上跳到那一层即可。(不一定是节点较浅的所在层,先往上跳可能更近,从根节点条避免高精度);
由于二叉树上的点序号有lc=fa*2,rc=fa*2+1,且同层为
这里写代码片#include<iostream>#include<cstdio>#include<cstring>#include<string>#include<algorithm>using namespace std;const int N=1e5+5;struct tree{ int lazy,sum,len;}tr[N<<2];int s[N],t[N],sn,tn;void build(int l,int r,int now){ tr[now].len=r-l+1; if(l==r)return; int mid=l+r>>1; build(l,mid,now<<1); build(mid+1,r,now<<1|1);}void add_lazy(int now ,int lazy){ tr[now].lazy=lazy; tr[now].sum=(lazy-1)*tr[now].len;}void pushdown(int now){ if(tr[now].lazy) { add_lazy(now<<1,tr[now].lazy); add_lazy(now<<1|1,tr[now].lazy); tr[now].lazy=0; }}void update(int now){ tr[now].sum=tr[now<<1].sum+tr[now<<1|1].sum;}void modify(int l,int r,int now,int x,int y,int z){ if(x<=l&&r<=y)return add_lazy(now,z); int mid=l+r>>1; pushdown(now); if(x<=mid)modify(l,mid,now<<1,x,y,z); if(y>mid)modify(mid+1,r,now<<1|1,x,y,z); update(now);}int query_l(int l,int r,int now,int x)//进位找连续的1打标记 ,这里找的是从x位往前第一个0. { if(x<l)return 0; if(tr[now].sum==tr[now].len)return 0; if(l==r)return tr[now].sum==0?l:0; int mid=l+r>>1; pushdown(now); int ret=query_l(mid+1,r,now<<1|1,x); if(!ret)ret=query_l(l,mid,now<<1,x); return ret;}int query_r(int l,int r,int now,int x)//退位找连续的0打标记 ,这里找的是从x位往前第一个1. { if(x<l)return 0; if(tr[now].sum==0)return 0; if(l==r)return tr[now].sum==1?l:0; int mid=l+r>>1; pushdown(now); int ret=query_r(mid+1,r,now<<1|1,x); if(!ret)ret=query_r(l,mid,now<<1,x); return ret;}void tree_export(int l,int r,int now,int x,int *p){ if(l==r) { p[l]=tr[now].sum; return; } int mid=l+r>>1; pushdown(now); tree_export(l,mid,now<<1,x,p); tree_export(mid+1,r,now<<1|1,x,p);}void read(int *p,int &n){ static char s[N]; scanf("%s",s+1); int mx=strlen(s+1); build(1,mx,1); n=0; for(int i=1;i<=mx;i++) { if(s[i]=='1') { ++n,modify(1,mx,1,n,n,1); continue; } if(s[i]=='2') { ++n,modify(1,mx,1,n,n,2); continue; } if(s[i]=='U') { n--; continue; } if(s[i]=='L') { int pos=query_r(1,mx,1,n); modify(1,mx,1,pos+1,n,2); modify(1,mx,1,pos,pos,1); } if(s[i]=='R') { int pos=query_l(1,mx,1,n); modify(1,mx,1,pos+1,n,1); modify(1,mx,1,pos,pos,2); } } tree_export(1,mx,1,n,p);}int main(){ //freopen("lx.in","r",stdin); read(s,sn),read(t,tn); int sum=abs(sn-tn); int n=min(sn,tn); int ans=2*n,dist=0; for(int i=1;i<=n;i++) { if(s[i]==t[i])dist*=2; else if(s[i]<t[i])dist=dist*2+1; else { dist=dist*2-1; if(dist<0)swap(s,t),dist*=-1; } if(dist>ans)break; ans=min(ans,dist+2*(n-i)); } cout<<sum+ans<<endl; return 0;}
- NOIP模拟 Board
- [NOIP2017模拟]board
- Noip模拟
- 【NOIP模拟】20151004模拟
- 【NOIP模拟】 20151005模拟
- 【NOIP模拟】 20151006模拟
- 【NOIP模拟】 20151007模拟
- 【NOIP模拟】20151014模拟
- 【NOIP模拟】20151015模拟
- Board Silly(poj 1558)模拟
- 【09 NOIP 模拟】light
- [NOIP模拟]Day1
- 8.9CH NOIP模拟
- 8.10FCH NOIP模拟
- 8.13NOIP模拟
- 8.14NOIP模拟
- noip模拟赛 双城记
- Noip模拟总结
- 并发(七):闭锁应用与其实现原理
- [FWT+Nim游戏] BZOJ4589: Hard Nim
- PAT 1026程序运行时间
- ul 无序列表
- HTTP缓存原理介绍
- NOIP模拟 Board
- 字符串--用数组初始化和用指针初始化方法
- 互联网协议入门(一)
- for、while、do while循环结构
- xml的空标记、ANY、混合元素
- android 音乐播放器
- Windows启动远程抓包命令
- 欢迎使用CSDN-markdown编辑器
- I