题目链接:

https://acm.bnu.edu.cn/v3/problem_show.php?pid=52317

As Easy As Possible

Case Time Limit: 1000ms
Memory Limit: 524288KB
## 题意
> 给你一个只含'e','a','s','y'的字符串,问你区间[l,r]内像"easyeasyeasy"这样的最多"easy"重复的子序列,输出easy重复的次数。

题解

1、用倍增的思路来做,每个点只记录最靠近它的在它左边的那个字母的位置,比如'e'记录前面的'y','a'记录前面的'e','s'记录前面的'a'...。这样相当于得到了一些树形结构,用树上倍增的思路去做就可以了。

具体的看代码比较好理解。

其实主要的思路就是化整为0,对每个字母只考虑排在它前面的且最靠近它的在它左边的那个字母的位置。然后你发现这个就可以用树上倍增来快速求我们需要的子序列了。

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std; const int maxn=101010;
const int maxm=22; char str[maxn];
int arr[maxn],p3[maxn];
int n,m;
int anc[maxn][maxm];
int mp[4]; int main(){
scanf("%s",str+1);
n=strlen(str+1);
for(int i=1;i<=n;i++){
if(str[i]=='e') arr[i]=0;
else if(str[i]=='a') arr[i]=1;
else if(str[i]=='s') arr[i]=2;
else if(str[i]=='y') arr[i]=3;
} ///mp[i]存数字i最后出现的位置
memset(mp,0,sizeof(mp));
for(int i=1;i<=n;i++){
int pre=(arr[i]-1+4)%4;
anc[i][0]=mp[pre];
mp[arr[i]]=i;
p3[i]=mp[3];
} memset(anc[0],0,sizeof(anc[0])); for(int j=1;j<maxm;j++){
for(int i=1;i<=n;i++){
anc[i][j]=anc[anc[i][j-1]][j-1];
}
} scanf("%d",&m);
while(m--){
int l,r;
scanf("%d%d",&l,&r);
int v=p3[r];
int res=1;
for(int j=maxm-1;j>=0;j--){
if(anc[v][j]>=l){
v=anc[v][j];
res+=1<<j;
}
}
printf("%d\n",res/4);
} return 0;
}

2、主席树:

从前晚后建树,如果单前不是'y',那么rt[i]=rt[i-1],如果是的话,就贪心匹配,找到左边最接近的"eas",rt[i]=rt['e'前一个位置-1],然后把e的位置插到rt[i]这颗线段树中。

对于查询[l,r],直接去rt[r]中查找区间(l,r)的和就可以了。

相当于每颗线段树rt[i]维护了以i为结尾的区间的往左边贪心的最长"easyeasyeasy..."的子串。

#include<map>
#include<set>
#include<cmath>
#include<queue>
#include<stack>
#include<ctime>
#include<vector>
#include<cstdio>
#include<string>
#include<bitset>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<functional>
using namespace std;
#define X first
#define Y second
#define mkp make_pair
#define lson(i) (tre[(i)].ls)
#define rson(i) (tre[(i)].rs)
#define sumv(i) (tre[(i)].sum)
#define mid (l+(r-l)/2)
#define sz() size()
#define pb(v) push_back(v)
#define all(o) (o).begin(),(o).end()
#define clr(a,v) memset(a,v,sizeof(a))
#define bug(a) cout<<#a<<" = "<<a<<endl
#define rep(i,a,b) for(int i=a;i<(b);i++)
#define scf scanf
#define prf printf typedef long long LL;
typedef vector<int> VI;
typedef pair<int,int> PII;
typedef vector<pair<int,int> > VPII; const int INF=0x3f3f3f3f;
const LL INFL=0x3f3f3f3f3f3f3f3fLL;
const double eps=1e-8;
const double PI = acos(-1.0); //start---------------------------------------------------------------------- const int maxn=101010; ///nlogn空间复杂度
struct Tre {
int ls,rs,sum;
Tre() {
ls=rs=sum=0;
}
} tre[maxn*20]; int rt[maxn],tot; int _pos;
void update(int &o,int l,int r) {
tre[++tot]=tre[o],o=tot;
if(l==r) {
sumv(o)++;
} else {
if(_pos<=mid) update(lson(o),l,mid);
else update(rson(o),mid+1,r);
sumv(o)=sumv(lson(o))+sumv(rson(o));
}
} int _res,ql,qr;
void query(int o,int l,int r){
if(ql<=l&&r<=qr){
_res+=sumv(o);
}else{
if(ql<=mid) query(lson(o),l,mid);
if(qr>mid) query(rson(o),mid+1,r);
}
} char str[maxn];
int n,m; void init(){
rt[0]=tot=0;
} int solve(int pos){
int pre=0;
while(pos>0){
if(str[pos]=='s'&&pre==0) pre=1;
else if(str[pos]=='a'&&pre==1) pre=2;
else if(str[pos]=='e'&&pre==2) pre=3;
if(pre==3) break;
pos--;
}
return pos;
} int main() {
scf("%s",str+1);
n=strlen(str+1);
init();
for(int i=1;i<=n;i++){ if(str[i]=='y'){
_pos=solve(i-1);
if(_pos>0){
rt[i]=rt[_pos-1];
update(rt[i],1,n);
}else{
rt[i]=rt[i-1];
}
}else{
rt[i]=rt[i-1];
}
} scf("%d",&m);
while(m--){
int l,r;
scf("%d%d",&l,&r);
ql=l,qr=r,_res=0;
query(rt[r],1,n);
prf("%d\n",_res);
} return 0;
} //end-----------------------------------------------------------------------

BNUOJ 52317 As Easy As Possible 树上倍增/主席树的更多相关文章

  1. 【BZOJ 3551】[ONTAK2010] Peaks加强版 Kruskal重构树+树上倍增+主席树

    这题真刺激...... I.关于Kruskal重构树,我只能开门了,不过补充一下那玩意还是一棵满二叉树.(看一下内容之前请先进门坐一坐) II.原来只是用树上倍增求Lca,但其实树上倍增是一种方法,L ...

  2. 【codeforces666E】Forensic Examination 广义后缀自动机+树上倍增+线段树合并

    题目描述 给出 $S$ 串和 $m$ 个 $T_i$ 串,$q$ 次询问,每次询问给出 $l$ .$r$ .$x$ .$y$ ,求 $S_{x...y}$ 在 $T_l,T_{l+1},...,T_r ...

  3. BZOJ 2588: Spoj 10628. Count on a tree 树上跑主席树

    2588: Spoj 10628. Count on a tree Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://www.lydsy.com/J ...

  4. SPOJ 10628 COT - Count on a tree(在树上建立主席树)(LCA)

    COT - Count on a tree #tree You are given a tree with N nodes.The tree nodes are numbered from 1 to ...

  5. (2016北京集训十三)【xsy1532】网络战争 - 最小割树+树上倍增+KD树

    题解: 好题!! 这题似乎能上我代码长度记录的前五? 调试时间长度应该也能上前五QAQ 首先题目要求的明显就是最小割,当然在整个森林上求Q次最小割肯定是会GG的,所以我们需要一个能快速求最小割的算法— ...

  6. HDU 4729 An Easy Problem for Elfness (主席树,树上第K大)

    转载请注明出处,谢谢http://blog.csdn.net/ACM_cxlove?viewmode=contents    by---cxlove 题意:给出一个带边权的图.对于每一个询问(S , ...

  7. BZOJ4771 七彩树(dfs序+树上差分+主席树)

    考虑没有深度限制怎么做.显然的做法是直接转成dfs序上主席树,但如果拓展到二维变成矩形数颜色数肯定没法做到一个log. 另一种做法是利用树上差分.对于同种颜色的点,在每个点处+1,dfs序相邻点的lc ...

  8. BZOJ4539 [Hnoi2016]树 【倍增 + 主席树】

    题目链接 BZOJ4539 题解 我们把每次复制出来的树看做一个点,那么大树实际上也就是一棵\(O(M)\)个点的树 所以我们只需求两遍树上距离: 大树上求距离,进入同一个点后在模板树上再求一次距离 ...

  9. HDU 4729 An Easy Problem for Elfness(主席树)(2013 ACM/ICPC Asia Regional Chengdu Online)

    Problem Description Pfctgeorge is totally a tall rich and handsome guy. He plans to build a huge wat ...

随机推荐

  1. mysql获取随机题目、排序

    mysql排序问题(对字符串类型数据进行排序)对普通数字字符串字段排序:select * from qq ORDER BY score*1 DESC,time*1 ASC 一.在mysql操作中我们经 ...

  2. Android TV 全屏无标题

    想要全部窗口全屏无标题,修改 res\values\styles.xml 可设置主题和样式 <resources> <!-- Base application theme, depe ...

  3. Linux下onvif客户端获取h265 IPC摄像头的RTSP地址

    1. 设备搜索,去获取webserver 的地址 ,目的是在获取能力提供服务地址,demo:https://www.cnblogs.com/croxd/p/10683429.html 2. GetCa ...

  4. C 语言数组越界导致死循环问题

    今天朋友问我一道 C 语言的题目,如下图: 看到这题一开始也比较纳闷,arr[10] 不是越界了吗?怎么会死循环?怎么 arr[10] 就是 m?这是什么意思? 我们先来看一个简单的例子: ]; ; ...

  5. MongoDB操作-备份和恢复,导入和导出

    mongodb数据备份和恢复主要分为二种:一种是针对库的mongodump和mongorestore,一种是针对库中表的mongoexport和mongoimport 1. 常用命令格式 mongod ...

  6. JS如何捆绑TypeScript声明文件

    前话 TypeScript是JavaScript类型的超集 这是TypeScript的文档介绍的一句话,那么他们存在联系呢? 我的理解是,TypeScript在JavaScript基础上引入强类型语言 ...

  7. 负载均衡@StackExchange.Redis实现Session外置--纯干货喂饱你

    Redis和StackExchange.Redis redis有多个数据库1.redis 中的每一个数据库,都由一个 redisDb 的结构存储.其中,redisDb.id 存储着 redis 数据库 ...

  8. lua编程之协程介绍

    一,lua协程简介 协程(coroutine),意思就是协作的例程,最早由Melvin Conway在1963年提出并实现.跟主流程序语言中的线程不一样,线程属于侵入式组件,线程实现的系统称之为抢占式 ...

  9. 大学生Linux常用命令(一)

    大学生Linux常用命令(一) 1.1 命令格式 命令格式一般为---命令名 [选项] [参数1] [参数2]- 例如:cp -I file1 cp为命令名,-l为选项,file1为参数. 其中,命令 ...

  10. Docker部署MySQL容器

    从仓库下载镜像 sudo docker pull mysql:5.7   创建容器 docker run --name="mysql" \ -p 3306:3306 \ -v /U ...