首先预处理出$f[i][j][k]$表示长度为$i$的序列,第一个位置是$j$,最后一个位置是$k$时合法的方案数。

从后往前枚举LCP以及那个位置应该改成什么。

用线段树维护区间内最左最右的已经确定的位置,以及区间内的合法方案数。

合并的时候只需要将左右儿子的答案乘起来,然后再乘以左儿子最右到右儿子最左这一段区间的方案数即可。

时间复杂度$O(n\log n)$。

#include<cstdio>
const int N=400010,M=1050000,P=1000000007;
int n,m,i,j,k,x,a[N],g[3][3],f[N][3][3],pos[N],v[N],l[M],r[M],val[M],ans=1;char ch[9],s[N];
inline void read(int&a){char c;while(!(((c=getchar())>='0')&&(c<='9')));a=c-'0';while(((c=getchar())>='0')&&(c<='9'))(a*=10)+=c-'0';}
inline void up(int&x,int y){x+=y;if(x>=P)x-=P;}
void build(int x,int a,int b){
l[x]=a,r[x]=b,val[x]=1;
if(a==b){pos[a]=x;return;}
int mid=(a+b)>>1;
build(x<<1,a,mid),build(x<<1|1,mid+1,b);
}
inline bool change(int x,int p){
if(~p){
if(x>1&&~v[x-1])if(g[v[x-1]][p])return 0;
if(x<n&&~v[x+1])if(g[p][v[x+1]])return 0;
}
v[x]=p,x=pos[x];
if(p<0)l[x]=r[x]=0;
for(x>>=1;x;x>>=1){
l[x]=l[x<<1]?l[x<<1]:l[x<<1|1];
r[x]=r[x<<1|1]?r[x<<1|1]:r[x<<1];
val[x]=1LL*val[x<<1]*val[x<<1|1]%P;
if(r[x<<1]&&l[x<<1|1])val[x]=1LL*val[x]*f[l[x<<1|1]-r[x<<1]+1][v[r[x<<1]]][v[l[x<<1|1]]]%P;
}
return 1;
}
inline int ask(){
int ret=val[1],t,i;
if(l[1]>1){
for(t=i=0;i<3;i++)up(t,f[l[1]][i][v[l[1]]]);
ret=1LL*ret*t%P;
}
if(r[1]<n){
for(t=i=0;i<3;i++)up(t,f[n-r[1]+1][v[r[1]]][i]);
ret=1LL*ret*t%P;
}
return ret;
}
int main(){
read(n);
for(i=1;i<=n;i++)read(a[i]);
read(m);
while(m--)scanf("%s",ch),g[ch[0]-'1'][ch[1]-'1']=1;
scanf("%s",s+1);
for(i=1;i<=n;i++)s[i]-='1',v[i]=s[i];
for(i=0;i<3;i++)f[1][i][i]=1;
for(i=1;i<n;i++)for(j=0;j<3;j++)for(k=0;k<3;k++)if(f[i][j][k])for(x=0;x<3;x++)if(!g[k][x])up(f[i+1][j][x],f[i][j][k]);
build(1,1,n);
for(i=n;i;change(a[i--],-1))for(j=0;j<s[a[i]];j++)if(change(a[i],j))up(ans,ask());
return printf("%d",ans),0;
}

  

BZOJ3019 : [Balkan2012]handsome的更多相关文章

  1. bzoj AC倒序

    Search GO 说明:输入题号直接进入相应题目,如需搜索含数字的题目,请在关键词前加单引号 Problem ID Title Source AC Submit Y 1000 A+B Problem ...

  2. [swustoj 443] Handsome Swap

    Handsome Swap(0443) Time limit(ms): 1000 Memory limit(kb): 65535 Submission: 89 Accepted: 20 Accepte ...

  3. BZOJ3024 : [Balkan2012]balls

    问题1: ans=max(sum[n]-(sum[i]-sum[j-1])+a[i]*(i-j+1)) =max(sum[n]-sum[i]+sum[j-1]+a[i]*(i+1)-a[i]*j) = ...

  4. 【BZOJ】3022: [Balkan2012]The Best Teams

    原题链接 题面 (为啥这题没有题面-- 给出\(N\)个人,和年龄\(age_{i},skill_{i}\) 然后给出\(M\)个询问,就是年龄在\(a\)以下选不超过\(k\)个人 要求选择的人水平 ...

  5. BZOJ3022 : [Balkan2012]The Best Teams

    将选手和询问按照年龄排序,即可去掉年龄的限制. 将所有选手按水平排序后维护线段树,显然最优解一定是从大到小贪心选择. 线段树上每个节点维护: $g[0/1]:r+1$不选/选的时候,$l$选不选. $ ...

  6. BZOJ 3022 [Balkan2012]The Best Teams(扫描线+线段树)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=3022 [题目大意] 给定n个球员,第i个球员年龄为AGEi,水平为SKILLi. 没有 ...

  7. Javascript实用方法二

    承接上一篇, Object keys object的keys方法能够获取一个给定对象的所有键(key/属性名)并以数组的形式返回.这个方法可以用于键的筛选.匹配等. var basket = { st ...

  8. 【NLP】Python NLTK获取文本语料和词汇资源

    Python NLTK 获取文本语料和词汇资源 作者:白宁超 2016年11月7日13:15:24 摘要:NLTK是由宾夕法尼亚大学计算机和信息科学使用python语言实现的一种自然语言工具包,其收集 ...

  9. 跟着老男孩教育学Python开发【第五篇】:模块

    递归的案例:阶乘 1*2*3*4*5*6*7- def func(num):     if num == 1:         return 1     return num * func(num - ...

随机推荐

  1. linux 查看用户上次修改密码的日期【转】

    1.找到以下文件: cat /etc/shadow 第三段字符就是最近一次密码修改的天数,此数字是距离1970年1月1日的天数.   2.用以下命令计算: date -u -d "1970- ...

  2. MySQL日志——Undo | Redo【转】

    本文是介绍MySQL数据库InnoDB存储引擎重做日志漫游 00 – Undo LogUndo Log 是为了实现事务的原子性,在MySQL数据库InnoDB存储引擎中,还用Undo Log来实现多版 ...

  3. php学习之mysqli的面向对象

    // mySqlTool.php  封装好的工具类 <?php class SqlTool{ private $conn; private $host="localhost" ...

  4. centos6.5环境搭建openvp服务器及windows客户端搭建及配置详解

    1.环境搭建 说明: vpn client 192.168.8.16/24 openvpn server: eth0: 192.168.8.41 eth1: 172.16.1.10 app serve ...

  5. 在jsp页面,将小数转换为百分比

    <fmt:formatNumber type="number" value="${temp.illegalCount*100/temp.unitCount}&quo ...

  6. jmeter之beanshell取出需要参数,传递给下个请求

    jmeter之beanshell取出需要参数,传递给下个请求 事件背景: 上周同事用jmeter录制脚本,录制成功回放后,并没有达到自己想要的结果. ps:他想从数据库取出某个字段值,然后对数据库做操 ...

  7. js的闭包的一个示例说明

    js中 某个函数的内部函数在该函数执行结束后仍然可以访问这个函数中定义的变量,这称为闭包(Closure) 复制代码 代码如下: function outside() { var myVar = 1; ...

  8. C++11 AUTO 类型实践

    auto在C++11中引入,为大家带来方便. 具体使用及注意事项参考: https://blog.csdn.net/xiaoquantouer/article/details/51647865 htt ...

  9. sublime text 3配置c/c++编译环境

    关于gcc和g++ 安装编译器是后面所有工作的基础,如果没有编译器,后面的一切都无从谈起.在windows下使用gcc和g++,是通过安装MinGW实现的. 安装MinGW MinGW是Minimal ...

  10. linux + docker + selenium grid 实现分布式执行selenium脚本

    Selenium Grid 有两个概念 hub :主节点,你可以看作 "北京总公司的测试经理". node:分支节点,你可以看作 "北京总公司的测试小兵A" 和 ...