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. ...
随机推荐
- HDU 2955 Robberies 背包概率DP
A - Robberies Time Limit:1000MS Memory Limit:32768KB 64bit IO Format:%I64d & %I64u Submi ...
- [ruby on rails] 跟我学之(5)显示所有数据
之前的index页,显示的是hello world,现在将其修改为显示我们在rails console里面录入的数据. 1. 修改action 如之前的章节<[ruby on rails] 跟我 ...
- Ubuntu上如何安装Java,Eclipse,Pydev,Python(自带,不用装),BeautifulSoup
如何安装Java,如果出于编程的需要安装Java,需要安装的是JDK,而不仅仅是JRE,下面说说如何在Ubuntu下如何安装JDK:只有两步,1.下载并解压,2.配置环境变量1.下载并解压:下载地址: ...
- users
NAME users - print the user names of users currently logged in to the current host SYNOPSIS users [O ...
- linux使用技巧
<1>vim /etc/hosts.deny sshd : 192.168.0.25 :deny //ssh拒绝某ip或网段访问.(原理详见鸟哥基础版18章P56 ...
- intellij idea 如何更改编辑器文本字体和大小
换上了intellij idea之后,第一件事就是想要改变下文字字体,因为在我这个27寸的2k分辨率的屏幕上,文字显然太小了. intellij idea字体设值分成两部分,一部分是UI部分字体字号设 ...
- SQL union和union all的区别
Union因为要进行重复值扫描,所以效率低.如果合并没有刻意要删除重复行,那么就使用Union All 两个要联合的SQL语句 字段个数必须一样,而且字段类型要“相容”(一致): 如果我们需要将两个 ...
- C++基础知识面试精选100题系列(1-10题)[C++ basics]
[原文链接] http://www.cnblogs.com/hellogiser/p/100-interview-questions-of-cplusplus-basics-1-10.html [题目 ...
- 如何用BMFont制作图片字
1: 运行程序,单击鼠标左键点亮相应位置的字母,比如:0.1.2./ 等2: 选择 Edit->Open Image Manager.弹出一个“Image Manager" 对话框3: ...
- Python多线程(1)——介绍
Python对多线程提供了很好的支持,Python中多线程相关的模块包括:thread,threading,Queue.可以方便地支持创建线程.互斥锁.信号量.同步等特性. 1. thread:多线程 ...