Description

给定N个仅有a~z组成的字符串ai,每个字符串都有一个权值vi,有M次操作,操作分三种:
Cv x v':把第x个字符串的权值修改为v'
Cs x a':把第x个字符串修改成a'
Q:求出当前的最大权字符串集合,使得这个集合中的字符串经过重新排列后满足除最后一个字符串外,前一个字符
串是后一个的前缀(两个字符串相同也是前缀关系,也可以一个字符串都不选)
前50%的数据可以接受离线算法,后50%的数据要求在线算法。

Input

输入的第一行包含一个正整数Test表示当前的数据类型。
输入的第二行包含两个正整数N,M表示字符串数和操作数。
以下N行,每行一个字符串ai
第N+3行包含N个整数vi
以下M行,为M次操作,操作有三种Cv x v',Cs x a',Q,第三种操作如题目描述一样,对于Test=1的修改操作,不用
做 任何变化,对于Test=2的修改操作,假设当前最后一次询问操作的答案是ans(如果还没有询问操作,ans=0),那
么对于第 一种操作中的v'=min(1000,v'+(ans mod 1000)),对于第二种操作的字符串a',它的每一位都要加上ans m
od 26(a~z循环)
数据分两种,A类数据可以用离线的方法来完成,B类数据必须使用在线算法。
令len=输入数据中所有出现的字符串总长度
数据分两种,A类数据可以用离线的方法来完成,B类数据必须使用在线算法。
N<=50000,M<=10^5,Len<=10^6
 
 

Output

对于每一次询问输出合法的最大权字符串集合的权值和

Sample Input

1
5 5
aba
ab
babb
abaa
abab
-2 1 4 2 3
Q
Cv 1 2
Q
Cs 3 abaab
Q

Sample Output

4
6
9

解题思路:

相当于插寻trie树上到根节点最大权路径。
修改单点对子树产生贡献。
每次插入/删除一条链。
Dfs序动态维护就好了。
代码1(卡常压缩版100行):
 #include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
typedef long long lnt;
struct trnt{int L,R,fa,rnd,wgt,val,ind,len,mxv,lzt_l,lzt_v;}T[];
struct trie{int ch[],val;}t[];
int Rt,Rtl,Rtm,Rtr,siz,n,m,Tn,H;
char cmd[],str[];
int pos[],val[];
inline int Rd(void){
int ans=,f=;char ch=getchar();while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch<=''&&ch>=''){ans=ans*+ch-'';ch=getchar();}return ans*f;
}
inline void Up(int W){
const int Z=T[W].L,C=T[W].R;
T[W].wgt=,T[W].mxv=T[W].val;
if(Z)T[W].mxv=std::max(T[W].mxv,T[Z].mxv),
T[W].wgt+=T[Z].wgt;T[Z].fa=W;
if(C)T[W].mxv=std::max(T[W].mxv,T[C].mxv),
T[W].wgt+=T[C].wgt;T[C].fa=W;
return ;
}
inline void A(int W,int v)
{if(!W)return ;T[W].val+=v,T[W].mxv+=v,T[W].lzt_v+=v;return ;}
inline void Al(int W,int l){if(!W)return ;T[W].ind+=l;T[W].lzt_l+=l;return ;}
inline void Dn(int W){
int &Z=T[W].L,&C=T[W].R;
if(T[W].lzt_v){A(Z,T[W].lzt_v);A(C,T[W].lzt_v);T[W].lzt_v=;}
if(T[W].lzt_l){Al(Z,T[W].lzt_l);Al(C,T[W].lzt_l);T[W].lzt_l=;}
return ;
}
inline void Rl(int W){if(T[W].fa)Rl(T[W].fa);Dn(W);return ;}
inline void St(int W,int k,int &ll,int &rr){
int &Z=T[W].L,&C=T[W].R;
if(!W)ll=rr=;
else{Dn(W);if(T[Z].wgt>=k){rr=W;St(Z,k,ll,Z);}else{ll=W;St(C,k-T[Z].wgt-,C,rr);}Up(W);}
return ;
}
inline int Mg(int ll,int rr){
if(!ll||!rr)return ll|rr;
if(T[ll].rnd<T[rr].rnd)
{Dn(ll);T[ll].R=Mg(T[ll].R,rr);Up(ll);return ll;}
else{Dn(rr);T[rr].L=Mg(ll,T[rr].L);Up(rr);return rr;}
return ;
}
inline int Rk(int W){
Rl(W);
int Z=T[W].L,ans=T[Z].wgt+;
while(W){if(T[T[W].fa].R==W)ans+=T[T[T[W].fa].L].wgt+;W=T[W].fa;}
return ans;
}
inline void Bc(char *a,int from,int len,int &rt,int v){
int dlt=len-from+;Rl(rt);
St(Rt,T[rt].ind-,Rtl,Rtr);
St(Rtr,T[rt].len,Rtm,Rtr);
int dfn=T[rt].ind+T[rt].len-;
for(int i=from;i<=len;i++){
dfn++;int c=a[i]-'a';t[rt].ch[c]=++siz;T[siz].rnd=rand();
T[siz].val=v;T[siz].wgt=;T[siz].ind=dfn;T[siz].len=len-i+;
Rtm=Mg(Rtm,siz);rt=t[rt].ch[c];
}
int ROOT=;for(int i=;i<=from;i++){int c=a[i]-'a';T[ROOT].len+=dlt;ROOT=t[ROOT].ch[c];}
Rt=Mg(Mg(Rtl,Rtm),Rtr);St(Rt,Rk(siz),Rtl,Rtr);
if(Rtr)Al(Rtr,dlt);Rt=Mg(Rtl,Rtr);return ;
}
inline void Is(char *a,int &rt){
rt=;int len=strlen(a+),v=;
for(int i=;i<=len;i++){
int c=a[i]-'a';v+=t[rt].val;
if(!t[rt].ch[c])return Bc(a,i,len,rt,v);rt=t[rt].ch[c];
}return ;
}
inline void Cd(int i,int f){
t[pos[i]].val+=f*val[i];Rl(pos[i]);St(Rt,T[pos[i]].ind-,Rtl,Rtr);
St(Rtr,T[pos[i]].len,Rtm,Rtr);A(Rtm,val[i]*f);
Rt=Mg(Mg(Rtl,Rtm),Rtr);return ;
}
int main()
{
Tn=Rd();n=Rd();m=Rd();Rt=++siz;T[Rt].rnd=rand();
T[Rt].len=T[Rt].ind=;
for(int i=;i<=n;i++)scanf("%s",str+),Is(str,pos[i]);
for(int i=;i<=n;i++){val[i]=Rd();if(val[i]<=)val[i]=;else Cd(i,);}
while(m --> ){
scanf("%s",cmd+);
if(cmd[]=='Q')printf("%d\n",H=T[Rt].mxv);
if(cmd[]=='v'){
int x=Rd(),v=Rd();if(Tn==)v=std::min(,v+H%);
Cd(x,-);if(v<=)v=;val[x]=v;Cd(x,);
}
if(cmd[]=='s'){
int x=Rd();scanf("%s",str+);
if(Tn==){int len=strlen(str+);
for(int i=;i<=len;i++)str[i]=((int)(str[i]-'a')+H)%+'a';}
Cd(x,-);Is(str,pos[x]);Cd(x,);
}
}
return ;
}

极限版

代码2:

 #include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#define lll tr[spc].ls
#define rrr tr[spc].rs
typedef long long lnt;
inline int read(void)
{
int ans=,f=;
char ch=getchar();
while(ch<''||ch>'')
{
if(ch=='-')f=-;
ch=getchar();
}
while(ch>=''&&ch<='')
{
ans=ans*+ch-'';
ch=getchar();
}
return ans*f;
}
struct trnt{
int ls;
int rs;
int fa;
int rnd;
int wgt;
int val;
int ind;
int len;
int mxv;
int lzt_l;
int lzt_v;
}tr[];
struct trie{
int ch[];
int val;
}t[];
int root;
int rootl;
int rootm;
int rootr;
int siz;
int n,m;
int testno;
int lastans;
char cmd[];
int pos[];
int val[];
char str[];
inline void pushup(int spc)
{
tr[spc].wgt=;
tr[spc].mxv=tr[spc].val;
if(lll)
{
tr[spc].mxv=std::max(tr[spc].mxv,tr[lll].mxv);
tr[spc].wgt+=tr[lll].wgt;
tr[lll].fa=spc;
}
if(rrr)
{
tr[spc].mxv=std::max(tr[spc].mxv,tr[rrr].mxv);
tr[spc].wgt+=tr[rrr].wgt;
tr[rrr].fa=spc;
}
return ;
}
inline void ADD(int spc,int v)
{
if(!spc)return ;
tr[spc].val+=v;
tr[spc].mxv+=v;
tr[spc].lzt_v+=v;
return ;
}
inline void ADDLEN(int spc,int l)
{
if(!spc)return ;
tr[spc].ind+=l;
tr[spc].lzt_l+=l;
return ;
}
inline void pushdown(int spc)
{
if(tr[spc].lzt_v)
{
ADD(lll,tr[spc].lzt_v);
ADD(rrr,tr[spc].lzt_v);
tr[spc].lzt_v=;
}
if(tr[spc].lzt_l)
{
ADDLEN(lll,tr[spc].lzt_l);
ADDLEN(rrr,tr[spc].lzt_l);
tr[spc].lzt_l=;
}
return ;
}
void recal(int spc)
{
if(tr[spc].fa)recal(tr[spc].fa);
pushdown(spc);
return ;
}
void split(int spc,int k,int &ll,int &rr)
{
if(!spc)ll=rr=;
else{
pushdown(spc);
if(tr[lll].wgt>=k)
{
rr=spc;
split(lll,k,ll,lll);
}else{
ll=spc;
split(rrr,k-tr[lll].wgt-,rrr,rr);
}
pushup(spc);
}
return ;
}
int merge(int ll,int rr)
{
if(!ll||!rr)return ll|rr;
if(tr[ll].rnd<tr[rr].rnd)
{
pushdown(ll);
tr[ll].rs=merge(tr[ll].rs,rr);
pushup(ll);
return ll;
}else{
pushdown(rr);
tr[rr].ls=merge(ll,tr[rr].ls);
pushup(rr);
return rr;
}
return ;
}
int rank(int spc)
{
recal(spc);
int ans=tr[lll].wgt+;
while(spc)
{
if(tr[tr[spc].fa].rs==spc)ans+=tr[tr[tr[spc].fa].ls].wgt+;
spc=tr[spc].fa;
}
return ans;
}
void build_chain(char *a,int from,int len,int &rt,int v)
{
int dlt=len-from+;
int ROOT=;
recal(rt);
split(root,tr[rt].ind-,rootl,rootr);
split(rootr,tr[rt].len,rootm,rootr);
int dfn=tr[rt].ind+tr[rt].len-;
for(int i=from;i<=len;i++)
{
dfn++;
int c=a[i]-'a';
t[rt].ch[c]=++siz;
tr[siz].rnd=rand();
tr[siz].val=v;
tr[siz].wgt=;
tr[siz].ind=dfn;
tr[siz].len=len-i+;
rootm=merge(rootm,siz);
rt=t[rt].ch[c];
}
for(int i=;i<=from;i++)
{
int c=a[i]-'a';
tr[ROOT].len+=dlt;
ROOT=t[ROOT].ch[c];
}
root=merge(merge(rootl,rootm),rootr);
split(root,rank(siz),rootl,rootr);
if(rootr)ADDLEN(rootr,dlt);
root=merge(rootl,rootr);
return ;
}
void insert(char *a,int &rt)
{
int len=strlen(a+);
rt=;
int v=;
for(int i=;i<=len;i++)
{
int c=a[i]-'a';
v+=t[rt].val;
if(!t[rt].ch[c])return build_chain(a,i,len,rt,v);
rt=t[rt].ch[c];
}
return ;
}
void change_dfn(int i,int f)
{
t[pos[i]].val+=f*val[i];
recal(pos[i]);
split(root,tr[pos[i]].ind-,rootl,rootr);
split(rootr,tr[pos[i]].len,rootm,rootr);
ADD(rootm,val[i]*f);
root=merge(merge(rootl,rootm),rootr);
return ;
}
int main()
{
srand();
testno=read();
n=read();m=read();
root=++siz;
tr[root].rnd=rand();
tr[root].len=tr[root].ind=;
for(int i=;i<=n;i++)
{
scanf("%s",str+);
insert(str,pos[i]);
}
for(int i=;i<=n;i++)
{
val[i]=read();
if(val[i]<=)val[i]=;
else change_dfn(i,);
}
while(m --> )
{
scanf("%s",cmd+);
if(cmd[]=='Q')
printf("%d\n",lastans=tr[root].mxv);
if(cmd[]=='v')
{
int x=read(),v=read();
if(testno==)v=std::min(,v+lastans%);
change_dfn(x,-);
if(v<=)v=;
val[x]=v;
change_dfn(x,);
}
if(cmd[]=='s')
{
int x=read();
scanf("%s",str+);
if(testno==)
{
int len=strlen(str+);
for(int i=;i<=len;i++)
str[i]=((int)(str[i]-'a')+lastans)%+'a';
}
change_dfn(x,-);
insert(str,pos[x]);
change_dfn(x,);
}
}
return ;
}

BZOJ2690: 字符串游戏(平衡树动态维护Dfs序)的更多相关文章

  1. BZOJ3159决战——树链剖分+非旋转treap(平衡树动态维护dfs序)

    题目描述 输入 第一行有三个整数N.M和R,分别表示树的节点数.指令和询问总数,以及X国的据点. 接下来N-1行,每行两个整数X和Y,表示Katharon国的一条道路. 接下来M行,每行描述一个指令或 ...

  2. BZOJ3729Gty的游戏——阶梯博弈+巴什博弈+非旋转treap(平衡树动态维护dfs序)

    题目描述 某一天gty在与他的妹子玩游戏.妹子提出一个游戏,给定一棵有根树,每个节点有一些石子,每次可以将不多于L的石子移动到父节点,询问将某个节点的子树中的石子移动到这个节点先手是否有必胜策略.gt ...

  3. BZOJ3786星系探索——非旋转treap(平衡树动态维护dfs序)

    题目描述 物理学家小C的研究正遇到某个瓶颈. 他正在研究的是一个星系,这个星系中有n个星球,其中有一个主星球(方便起见我们默认其为1号星球),其余的所有星球均有且仅有一个依赖星球.主星球没有依赖星球. ...

  4. 【BZOJ 3729】3729: Gty的游戏 (Splay维护dfs序+博弈)

    未经博主同意不得转载 3729: Gty的游戏 Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 448  Solved: 150 Description ...

  5. BZOJ2690 : 字符串游戏

    离线算法: 先将所有涉及到的串建成字典树,然后用线段树维护dfs序,时间复杂度$O(m\log L)$. 在线算法: 用替罪羊树动态维护Trie树的dfs序即可,时间复杂度$O(L\log L)$. ...

  6. BZOJ_3729_Gty的游戏_博弈论+splay+dfs序

    BZOJ_3729_Gty的游戏_博弈论+splay+dfs序 Description 某一天gty在与他的妹子玩游戏. 妹子提出一个游戏,给定一棵有根树,每个节点有一些石子,每次可以将不多于L的石子 ...

  7. BZOJ 3881 [COCI2015]Divljak (Trie图+Fail树+树链的并+树状数组维护dfs序)

    题目大意: Alice有n个字符串S_1,S_2...S_n,Bob有一个字符串集合T,一开始集合是空的. 接下来会发生q个操作,操作有两种形式: “1 P”,Bob往自己的集合里添加了一个字符串P. ...

  8. CF877E Danil and a Part-time Job 线段树维护dfs序

    \(\color{#0066ff}{题目描述}\) 有一棵 n 个点的树,根结点为 1 号点,每个点的权值都是 1 或 0 共有 m 次操作,操作分为两种 get 询问一个点 x 的子树里有多少个 1 ...

  9. bzoj3991 [Sdoi2015]寻宝游戏 set动态维护虚树+树链求并

    题目大意:支持多次操作,增加或删除一个关键点 动态维护虚树边权和*2 分析:可以用树链求并的方法,最后减去虚树的根到1距离 注意到树链求并是所有点到根距离-所有dfn序相邻两点的LCA到根距离 找df ...

随机推荐

  1. 洛谷 P2730 魔板 Magic Squares

    P2730 魔板 Magic Squares 题目背景 在成功地发明了魔方之后,鲁比克先生发明了它的二维版本,称作魔板.这是一张有8个大小相同的格子的魔板: 1 2 3 4 8 7 6 5 题目描述 ...

  2. 实现图像剪裁 jquery.Jcrop

       配合 jquery.Jcrop 实现上传图片进行剪裁保存功能    <script src="js/jquery.min.js"></script> ...

  3. CodeForces 453A

    Twilight Sparkle was playing Ludo with her friends Rainbow Dash, Apple Jack and Flutter Shy. But she ...

  4. hadoop-11-ambari-server安装

    hadoop-11-ambari-server安装 #ambari 安装yum install ambari-servercd mysql-5.7.18/cp mysql-connector-java ...

  5. [React] Use React Fragments to make your DOM tree cleaner

    In this lesson, we will look at Fragments and how they are useful in achieving a cleaner DOM structu ...

  6. SpringMVC案例3----spring3.0项目拦截器、ajax、文件上传应用

    依然是项目结构图和所需jar包图: watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvYmVuamFtaW5fd2h4/font/5a6L5L2T/fontsi ...

  7. 【android】解决Viewpager设置高度为wrap_content无效的方法

    今天发现设置viewpager高度为wrap_content时并没作用.stackoverflow给出了解决方式,就是自己定义viewpager,重写onMesure()方法: public clas ...

  8. 海思 3520D 移植Qt4.5.3 一

    一.移植Qt4.5.3  1.获得 Qt4.5.3 的源码Qt4.5.3源码的原始包 qt-embedded-opensource-src-4.5.3.tar.gz 将其复制到 /opt 下,     ...

  9. bzoj1026: [SCOI2009]windy数(传说你是数位DP)

    1026: [SCOI2009]windy数 题目:传送门 题解: 其实之前年少无知的时候好像A过...表示当时并不知道什么数位DP 今天回来深造一发... 其实如果对这个算法稍有了解...看到这题的 ...

  10. svn服务器的搭建过程 主要为服务端

    yum -y install subversion 查看版本信息 svnserve --version 创建svn仓库目录 mkdir -p /var/svn/svnrepos 创建svn仓库 svn ...