BZOJ2690: 字符串游戏(平衡树动态维护Dfs序)
Description
Input
Output
对于每一次询问输出合法的最大权字符串集合的权值和
Sample Input
5 5
aba
ab
babb
abaa
abab
-2 1 4 2 3
Q
Cv 1 2
Q
Cs 3 abaab
Q
Sample Output
6
9
解题思路:
#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序)的更多相关文章
- BZOJ3159决战——树链剖分+非旋转treap(平衡树动态维护dfs序)
题目描述 输入 第一行有三个整数N.M和R,分别表示树的节点数.指令和询问总数,以及X国的据点. 接下来N-1行,每行两个整数X和Y,表示Katharon国的一条道路. 接下来M行,每行描述一个指令或 ...
- BZOJ3729Gty的游戏——阶梯博弈+巴什博弈+非旋转treap(平衡树动态维护dfs序)
题目描述 某一天gty在与他的妹子玩游戏.妹子提出一个游戏,给定一棵有根树,每个节点有一些石子,每次可以将不多于L的石子移动到父节点,询问将某个节点的子树中的石子移动到这个节点先手是否有必胜策略.gt ...
- BZOJ3786星系探索——非旋转treap(平衡树动态维护dfs序)
题目描述 物理学家小C的研究正遇到某个瓶颈. 他正在研究的是一个星系,这个星系中有n个星球,其中有一个主星球(方便起见我们默认其为1号星球),其余的所有星球均有且仅有一个依赖星球.主星球没有依赖星球. ...
- 【BZOJ 3729】3729: Gty的游戏 (Splay维护dfs序+博弈)
未经博主同意不得转载 3729: Gty的游戏 Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 448 Solved: 150 Description ...
- BZOJ2690 : 字符串游戏
离线算法: 先将所有涉及到的串建成字典树,然后用线段树维护dfs序,时间复杂度$O(m\log L)$. 在线算法: 用替罪羊树动态维护Trie树的dfs序即可,时间复杂度$O(L\log L)$. ...
- BZOJ_3729_Gty的游戏_博弈论+splay+dfs序
BZOJ_3729_Gty的游戏_博弈论+splay+dfs序 Description 某一天gty在与他的妹子玩游戏. 妹子提出一个游戏,给定一棵有根树,每个节点有一些石子,每次可以将不多于L的石子 ...
- BZOJ 3881 [COCI2015]Divljak (Trie图+Fail树+树链的并+树状数组维护dfs序)
题目大意: Alice有n个字符串S_1,S_2...S_n,Bob有一个字符串集合T,一开始集合是空的. 接下来会发生q个操作,操作有两种形式: “1 P”,Bob往自己的集合里添加了一个字符串P. ...
- CF877E Danil and a Part-time Job 线段树维护dfs序
\(\color{#0066ff}{题目描述}\) 有一棵 n 个点的树,根结点为 1 号点,每个点的权值都是 1 或 0 共有 m 次操作,操作分为两种 get 询问一个点 x 的子树里有多少个 1 ...
- bzoj3991 [Sdoi2015]寻宝游戏 set动态维护虚树+树链求并
题目大意:支持多次操作,增加或删除一个关键点 动态维护虚树边权和*2 分析:可以用树链求并的方法,最后减去虚树的根到1距离 注意到树链求并是所有点到根距离-所有dfn序相邻两点的LCA到根距离 找df ...
随机推荐
- 洛谷 P2730 魔板 Magic Squares
P2730 魔板 Magic Squares 题目背景 在成功地发明了魔方之后,鲁比克先生发明了它的二维版本,称作魔板.这是一张有8个大小相同的格子的魔板: 1 2 3 4 8 7 6 5 题目描述 ...
- 实现图像剪裁 jquery.Jcrop
配合 jquery.Jcrop 实现上传图片进行剪裁保存功能 <script src="js/jquery.min.js"></script> ...
- CodeForces 453A
Twilight Sparkle was playing Ludo with her friends Rainbow Dash, Apple Jack and Flutter Shy. But she ...
- hadoop-11-ambari-server安装
hadoop-11-ambari-server安装 #ambari 安装yum install ambari-servercd mysql-5.7.18/cp mysql-connector-java ...
- [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 ...
- SpringMVC案例3----spring3.0项目拦截器、ajax、文件上传应用
依然是项目结构图和所需jar包图: watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvYmVuamFtaW5fd2h4/font/5a6L5L2T/fontsi ...
- 【android】解决Viewpager设置高度为wrap_content无效的方法
今天发现设置viewpager高度为wrap_content时并没作用.stackoverflow给出了解决方式,就是自己定义viewpager,重写onMesure()方法: public clas ...
- 海思 3520D 移植Qt4.5.3 一
一.移植Qt4.5.3 1.获得 Qt4.5.3 的源码Qt4.5.3源码的原始包 qt-embedded-opensource-src-4.5.3.tar.gz 将其复制到 /opt 下, ...
- bzoj1026: [SCOI2009]windy数(传说你是数位DP)
1026: [SCOI2009]windy数 题目:传送门 题解: 其实之前年少无知的时候好像A过...表示当时并不知道什么数位DP 今天回来深造一发... 其实如果对这个算法稍有了解...看到这题的 ...
- svn服务器的搭建过程 主要为服务端
yum -y install subversion 查看版本信息 svnserve --version 创建svn仓库目录 mkdir -p /var/svn/svnrepos 创建svn仓库 svn ...