BZOJ2690 : 字符串游戏
离线算法:
先将所有涉及到的串建成字典树,然后用线段树维护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 : 字符串游戏的更多相关文章
- BZOJ2690: 字符串游戏(平衡树动态维护Dfs序)
Description 给定N个仅有a~z组成的字符串ai,每个字符串都有一个权值vi,有M次操作,操作分三种: Cv x v':把第x个字符串的权值修改为v' Cs x a':把第x个字符串修改成a ...
- BZOJ2121 字符串游戏
Description BX正在进行一个字符串游戏,他手上有一个字符串L,以及其 他一些字符串的集合S,然后他可以进行以下操作:对于一个在集合S中的字符串p,如果p在L中出现,BX就可以选择是否将其删 ...
- BZOJ2121: 字符串游戏(DP)(字符串删单词,求最多可以删去多少)
2121: 字符串游戏 Time Limit: 10 Sec Memory Limit: 259 MBSubmit: 672 Solved: 376[Submit][Status][Discuss ...
- 20181228 模拟赛 T3 字符串游戏 strGame 博弈论 字符串
3 字符串游戏(strGame.c/cpp/pas) 3.1 题目描述 pure 和 dirty 决定玩 T 局游戏.对于每一局游戏,有n个字符串,并且每一局游戏由K轮组成.具体规则如下:在每一轮 ...
- BZOJ 2121: 字符串游戏 区间DP + 思维
Description BX正在进行一个字符串游戏,他手上有一个字符串L,以及其他一些字符串的集合S,然后他可以进行以下操作:对 于一个在集合S中的字符串p,如果p在L中出现,BX就可以选择是否将其删 ...
- QuickHit项目(输出字符串游戏)
public class leve { private int leveNo; private int strLength; private int strTimes; private int tim ...
- 字符串游戏(strgame)——博弈
题目 [题目描述] pure 和 dirty 决定玩 $T$ 局游戏.对于每一局游戏,有 $n$ 个字符串,并且每一局游戏由 $K$ 轮组成.具体规则如下:在每一轮游戏中,最开始有一个空串,两者轮流向 ...
- noi.ac 字符串游戏
题面 Zhangzj和Owaski在玩一个游戏.最开始有一个空的01串,Zhangzj和Owaski轮流进行操作,Zhangzj先走.每次进行操作的人可以在串上任意位置加一个新的字符,由于串是01串, ...
- 【bzoj2121】字符串游戏 区间dp
题目描述 给你一个字符串L和一个字符串集合S,如果S的某个子串在S集合中,那么可以将其删去,剩余的部分拼到一起成为新的L串.问:最后剩下的串长度的最小值. 输入 输入的第一行包含一个字符串,表示L. ...
随机推荐
- hibernate.cfg.xml配置文件和hbm.xml配置文件 模板
hibernate.cfg.xml配置文件格式 <?xml version="1.0" encoding="UTF-8"?><!DOCTYPE ...
- Linux SUID SGID 讲解
SUID属性 UNIX的内核是根据什么来确定一个进程对资源的访问权限的呢? 是这个进程的运行用户的(有效)ID,包括user id和group id.用户可以用id命令来查到自己的或其他用户的user ...
- systemd在各个linux发行版的普及
后面我要说下自己的意见: 原则如果阻碍了进步,那还算个屁,不客气地说,UNIX 原则已经过时了. 移植性问题:我除了 Mac 外不用任何 BSD 系统,当然 Mac 上一般只做开发不做运维(但就算如此 ...
- 不使用arc功能时的编译参数 –fno-objc-arc
用一些老代码时,里面总有release调用,你需要用上这个标记,不使用arc功能编译代码.我总记不住具体写法,做个记录.
- 转mysql复制主从集群搭建
最近搭了个主从复制,中间出了点小问题,排查搞定,记录下来 1环境:虚拟机:OS:centos6.5Linux host2 2.6.32-431.el6.x86_64 #1 SMP Fri Nov 22 ...
- JavaScript关闭窗口的同时打开新页面的方法
做网页的时候需要弹出一个小窗口,然后要实现一个功能就是鼠标点击超链接关闭小窗口并打开一个新页面,就如同下图: 这是一个小窗口,点击超链接这个窗口会关闭并且会正常在浏览器打开新页面,首先写js关闭窗口的 ...
- ShortestPath:Six Degrees of Cowvin Bacon(POJ 2139)
牛与电影 题目大意:就是一群牛,又在玩游戏了(怎么你们经常玩游戏),这个游戏规则如下,把牛拆分成一个一个组,并且定义一个“度”,规定在一个组的牛与他自己的度为0,与其他牛的度为1,不同组的牛不存在度, ...
- linux下emacs配置文件
1:安装.在ubuntu下使用命令 sudo apt-get install emacs,即可,我使用的是ubuntu的10.04的版本,在里面使用了据说是163的2个源. 1.1:如何更新快速的源, ...
- JsRender语法
{{:#data.Name}} 或 {{:Name}} 直接显示html格式{{>#data.Name}} 或 {{>Name}} 转义显示html字符 if else {{if bool ...
- UVALive 7270 Osu! Master (阅读理解题)
题目:传送门. 题意:阅读理解题,是一个osu的游戏,问得分.把题目翻译过来就是如果出现S或者BC后面跟的是1,ans就加1. #include <iostream> #include & ...