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 ...
随机推荐
- 三 概要模式 3) MR计数器计数 。无 reduce 计数
计数器模式讲解: 先讲一下,就是说只用 Map 阶段 不需要 Reduce . 也就是说去掉了中间输出,而是Map 直接输出结果.大大提高了 MR 的效率且节省了 MR 中间输出读入 ...
- SVN配置以及自己主动部署到apache虚拟文件夹
SVN配置以及自己主动部署到apache虚拟文件夹 一.VisualSVN server 服务端和TortoiseSVNclient下载 VisualSVN下载:http://subversion.a ...
- python之路-------字符串与正則表達式
1.1.#####去掉字符串中的转义符string.strip() print "hello\tworld\n" >>> word="\thello w ...
- canvas为什么你指定一个比较小的宽高,但它实际占位却很多?
ccanvas默认的宽高占位是:300*150 px 所以当你画一个普通的举行,你指定的宽高小于默认宽高的时候,通过审查元素发现周围都是空白的.
- 在Ubuntu下使用命令删除目录
在Ubuntu命令行中用命令删除目录,现在在Linux系统中删除目录大致会用两个,rm和rmdir,rm命令删除目录很简单,不过很多人还是比较习惯用rmdir命令,如果操作的目录非空时就有点麻烦.这时 ...
- codeforces 404 B Marathon【fmod对浮点数取余】
题意:给出一个边长为a的正方形,给出d,给出n,输出走得距离为i个d的时候的坐标 学习的这一篇 http://blog.csdn.net/synapse7/article/details/215956 ...
- codeforces 495D Sonya and Matrix
Since Sonya has just learned the basics of matrices, she decided to play with them a little bit. Son ...
- Linux 运维笔试题(一)
试题: 1.说出下列服务对应的端口或者端口对应的服务 21 23 25 873 161 111 110 53 123 2049 2.文件atime,ctime,mtime的区 ...
- 运营商 WLAN
运营商 WLAN 运营商 WLAN 是 Android 9 中引入的一项功能,该功能可让设备自动连接到运营商实现的 WLAN 网络.在高度拥塞或信号覆盖范围较小的区域(如体育场或地铁站),运营商 WL ...
- bzoj1293 [SCOI2009] 生日礼物 队列
题目描述 小西有一条很长的彩带,彩带上挂着各式各样的彩珠.已知彩珠有N个,分为K种.简单的说,可以将彩带考虑为x轴,每一个彩珠有一个对应的坐标(即位置).某些坐标上可以没有彩珠,但多个彩珠也可以出现在 ...