离线算法:

先将所有涉及到的串建成字典树,然后用线段树维护dfs序,时间复杂度$O(m\log L)$。

在线算法:

用替罪羊树动态维护Trie树的dfs序即可,时间复杂度$O(L\log L)$。

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=2100010,M=50010;const double A=0.77;
int Type,n,m,i,x,y,loc[M],w[M],trie[N>>1][26],st[N>>1],en[N>>1],ct,ans;
char op[5],s[N];
namespace Subtask1{
int cnt,dfn,v[N],tag[N],c,d,p;
struct P{int x,y;P(){}P(int _x,int _y){x=_x,y=_y;}}q[250010];
void dfs(int x){
st[x]=++dfn;
for(int i=0;i<26;i++)if(trie[x][i])dfs(trie[x][i]);
en[x]=dfn;
}
inline void tag1(int x,int p){v[x]+=p;tag[x]+=p;}
void change(int x,int a,int b){
if(c<=a&&b<=d){tag1(x,p);return;}
if(tag[x])tag1(x<<1,tag[x]),tag1(x<<1|1,tag[x]),tag[x]=0;
int mid=(a+b)>>1;
if(c<=mid)change(x<<1,a,mid);
if(d>mid)change(x<<1|1,mid+1,b);
v[x]=max(v[x<<1],v[x<<1|1]);
}
inline void insert(int p){
gets(s);
int l=strlen(s);register int x=0,i=0;
for(int w;i<l;i++)if(s[i]>='a'){
if(!trie[x][w=s[i]-'a'])trie[x][w]=++ct;
x=trie[x][w];
}
loc[p]=x;
}
void work(){
for(i=1;i<=n;i++)insert(i);
for(i=1;i<=n;i++)scanf("%d",&w[i]),q[++cnt]=P(loc[i],max(w[i],0));
while(m--){
scanf("%s",op);
if(op[0]=='Q')q[++cnt]=P(-1,0);
if(op[1]=='v'){
scanf("%d%d",&x,&y);
q[++cnt]=P(loc[x],max(y,0)-max(w[x],0));
w[x]=y;
}
if(op[1]=='s'){
scanf("%d",&x);
if(w[x]>0)q[++cnt]=P(loc[x],-w[x]);
insert(x);
if(w[x]>0)q[++cnt]=P(loc[x],w[x]);
}
}
dfs(0);
for(i=1;i<=cnt;i++)if(q[i].x<0)printf("%d\n",v[1]);else c=st[q[i].x],d=en[q[i].x],p=q[i].y,change(1,1,dfn);
}
}
namespace Subtask2{
int size[N],son[N][2],val[N],h[N],tag[N],f[N],tot,root,data[N],id[N],cnt;
int P,B,C,D;
inline void umax(int&a,int b){if(a<b)a=b;}
inline int newnode(int x,int p,int fa){
f[x]=fa;size[x]=1;son[x][0]=son[x][1]=0;
h[x]=val[x]=p;tag[x]=0;
return x;
}
inline void tag1(int x,int p){h[x]+=p;val[x]+=p;tag[x]+=p;}
inline void pb(int x){
if(tag[x]){
if(son[x][0])tag1(son[x][0],tag[x]);
if(son[x][1])tag1(son[x][1],tag[x]);
tag[x]=0;
}
}
inline void up(int x){
h[x]=val[x];
if(son[x][0])umax(h[x],h[son[x][0]]);
if(son[x][1])umax(h[x],h[son[x][1]]);
}
int ins(int x){
size[x]++;pb(x);
if(!son[x][B])return son[x][B]=newnode(++tot,P,x);
return ins(son[x][B]);
}
void dfs(int x){
pb(x);
if(son[x][0])dfs(son[x][0]);
data[++cnt]=val[x];id[cnt]=x;
if(son[x][1])dfs(son[x][1]);
}
int build(int fa,int l,int r){
int mid=(l+r)>>1,x=newnode(id[mid],data[mid],fa);
if(l==r)return x;
if(l<mid)size[x]+=size[son[x][0]=build(x,l,mid-1)];
if(r>mid)size[x]+=size[son[x][1]=build(x,mid+1,r)];
return up(x),x;
}
inline int rebuild(int x){cnt=0;dfs(x);return build(f[x],1,cnt);}
inline int kth(int k){
register int x=root,rank,t;
while(1){
size[x]++;pb(x);
rank=size[son[x][0]]+1;
if(k==rank)return x;
if(k<rank)x=son[x][0];else k-=rank,x=son[x][1];
}
}
inline int rank(register int x){
int ans=size[son[x][0]]+1;
while(f[x]){
if(son[f[x]][1]==x)ans+=size[son[f[x]][0]]+1;
x=f[x];
}
return ans;
}
inline void kthins(int k){
register int x=kth(k);
if(son[x][0])B=1,x=ins(son[x][0]);else{
son[x][0]=newnode(++tot,P,x);
x=son[x][0];
}
while((double)size[son[x][0]]<A*size[x]&&(double)size[son[x][1]]<A*size[x])x=f[x];
if(!x)return;
if(x==root){root=rebuild(x);return;}
int y=f[x],b=son[y][1]==x,now=rebuild(x);
son[y][b]=now;
}
inline void modify(int x,int a,int b){
if(!x)return;
if(C<=a&&b<=D){tag1(x,P);return;}
pb(x);
int mid=a+size[son[x][0]];
if(C<=mid&&mid<=D)val[x]+=P;
if(C<mid)modify(son[x][0],a,mid-1);
if(D>mid)modify(son[x][1],mid+1,b);
up(x);
}
inline int getval(int x){
cnt=0;
for(register int i=x;i;i=f[i])id[++cnt]=i;
while(cnt)pb(id[cnt--]);
return val[x];
}
inline void addleaf(int x,int y){
int k=rank(en[x]);P=getval(en[x]);
st[y]=tot+2,en[y]=tot+1;
kthins(k);
kthins(k);
}
inline void subtreeadd(int x,int y){C=rank(st[x]),D=rank(en[x]),P=y;modify(root,1,tot);}
inline void insert(int p){
gets(s);
int l=strlen(s);register int x=0,i=0;
for(int w;i<l;i++)if(s[i]>='a'){
w=(s[i]-'a'+ans)%26;
if(!trie[x][w])addleaf(x,trie[x][w]=++ct);
x=trie[x][w];
}
loc[p]=x;
}
void work(){
root=build(0,st[0]=id[1]=1,tot=en[0]=id[2]=2);
for(i=1;i<=n;i++)insert(i);
for(i=1;i<=n;i++)scanf("%d",&w[i]),subtreeadd(loc[i],max(w[i],0));
while(m--){
scanf("%s",op);
if(op[0]=='Q')printf("%d\n",ans=h[root]);
if(op[1]=='v'){
scanf("%d%d",&x,&y);
y=min(1000,y+ans%1000);
subtreeadd(loc[x],max(y,0)-max(w[x],0));
w[x]=y;
}
if(op[1]=='s'){
scanf("%d",&x);
if(w[x]>0)subtreeadd(loc[x],-w[x]);
insert(x);
if(w[x]>0)subtreeadd(loc[x],w[x]);
}
}
}
}
int main(){
scanf("%d%d%d",&Type,&n,&m);gets(s);
if(Type==1)Subtask1::work();else Subtask2::work();
return 0;
}

  

BZOJ2690 : 字符串游戏的更多相关文章

  1. BZOJ2690: 字符串游戏(平衡树动态维护Dfs序)

    Description 给定N个仅有a~z组成的字符串ai,每个字符串都有一个权值vi,有M次操作,操作分三种: Cv x v':把第x个字符串的权值修改为v' Cs x a':把第x个字符串修改成a ...

  2. BZOJ2121 字符串游戏

    Description BX正在进行一个字符串游戏,他手上有一个字符串L,以及其 他一些字符串的集合S,然后他可以进行以下操作:对于一个在集合S中的字符串p,如果p在L中出现,BX就可以选择是否将其删 ...

  3. BZOJ2121: 字符串游戏(DP)(字符串删单词,求最多可以删去多少)

    2121: 字符串游戏 Time Limit: 10 Sec  Memory Limit: 259 MBSubmit: 672  Solved: 376[Submit][Status][Discuss ...

  4. 20181228 模拟赛 T3 字符串游戏 strGame 博弈论 字符串

    3  字符串游戏(strGame.c/cpp/pas) 3.1  题目描述 pure 和 dirty 决定玩 T 局游戏.对于每一局游戏,有n个字符串,并且每一局游戏由K轮组成.具体规则如下:在每一轮 ...

  5. BZOJ 2121: 字符串游戏 区间DP + 思维

    Description BX正在进行一个字符串游戏,他手上有一个字符串L,以及其他一些字符串的集合S,然后他可以进行以下操作:对 于一个在集合S中的字符串p,如果p在L中出现,BX就可以选择是否将其删 ...

  6. QuickHit项目(输出字符串游戏)

    public class leve { private int leveNo; private int strLength; private int strTimes; private int tim ...

  7. 字符串游戏(strgame)——博弈

    题目 [题目描述] pure 和 dirty 决定玩 $T$ 局游戏.对于每一局游戏,有 $n$ 个字符串,并且每一局游戏由 $K$ 轮组成.具体规则如下:在每一轮游戏中,最开始有一个空串,两者轮流向 ...

  8. noi.ac 字符串游戏

    题面 Zhangzj和Owaski在玩一个游戏.最开始有一个空的01串,Zhangzj和Owaski轮流进行操作,Zhangzj先走.每次进行操作的人可以在串上任意位置加一个新的字符,由于串是01串, ...

  9. 【bzoj2121】字符串游戏 区间dp

    题目描述 给你一个字符串L和一个字符串集合S,如果S的某个子串在S集合中,那么可以将其删去,剩余的部分拼到一起成为新的L串.问:最后剩下的串长度的最小值. 输入 输入的第一行包含一个字符串,表示L. ...

随机推荐

  1. 快还要更快,让PHP 7 运行更加神速

    导读 PHP 7 比5.x 快上很多,即使只有单纯的版本升级就已经很有感,不过大家还是希望它变得越来越快,这时再做些小调整就会更有fu,Let's try it! 事前准备 说到PHP 7,那一定跑不 ...

  2. ■SQL注入自学[第三学:注入点的读写、out_file]

    00x1 判断是否可读 code: http:.php?id and (select count(*) from mysql.user) >0--/*返回正确的话,说明没有是有读的权限.返回错误 ...

  3. Java修改数组长度

    java中没有关于修改数组长度的api,在此本人提供了修改数组长度的两个函数:arrayAddLength()和arrayReduceLength().详细见代码.  [java] view plai ...

  4. ubuntu12.04 Daemon的简单实现

    使用命令 start-stop-daemon 官方文档:http://manpages.ubuntu.com/manpages/lucid/en/man8/start-stop-daemon.8.ht ...

  5. css排版

    先介绍如何设定字体.颜色.大小.段落空白等比较简单的应用,后面再介绍下比如首字下沉.首行缩进.最后讲一些常用的web页面中文排版,比如中文字的截断.固定宽度词内折行(word-wrap和word-br ...

  6. 【leetcode】String to Integer (atoi)

    String to Integer (atoi) Implement atoi to convert a string to an integer. Hint: Carefully consider ...

  7. Powershell 批量替换文件

    Powershell 批量替换文件 ##作者:Xiongpq ##时间:2015-06-10 18:50 ##版本:2.0 ##源文件目录 ##源文件目录的所有文件都会覆盖目标目录的同名文件,源文件目 ...

  8. Diablo3

    1.装备 主手:元素弓 副手:精细箭袋 头: 胸:燃火外套 手:娜塔亚的手感 护腕:稳击护腕 戒指:罗盘玫瑰+布尔凯索的婚戒 颈部:旅者之誓 腰:科雷姆的强力腰带(速度加25%) 腿:深渊挖掘裤 脚: ...

  9. grep' \b\b'

    \b单词锁定符,如: '\bgrep\b'只匹配grep [root@86 ttf-arphic-uming-0.0.20050501]# cat /proc/diskstats 1 0 ram0 0 ...

  10. mybatis 如何查找表里的某一个字段,然后返回它们的结果集list ?

    <select id="findArgByParams" resultType="string" parameterType="map" ...