题意:

Description

n列火车,每条有l节车厢。每节车厢有一种颜色(用小写字母表示)。有m次车厢交换操作。求:对于每列火车,在交换车厢的某个时刻,与其颜色完全相同的火车最多有多少。

Input

n l m (2 ≤ n ≤ 1000, 1 ≤ l ≤ 100, 0 ≤ m ≤ 100000) n行字符串,长度为l

m行,每行4个数a b c d,a车的第b个字符与c车第d个字符交换。

Output

n个数,在交换车厢的某个时刻,与该车颜色完全相同的火车最多数目。

题解:

由于$l$很小,可以直接哈希判断两列火车是否相同;

用splay来维护所有火车的哈希值,每次交换操作直接删除两个串的哈希值,交换字符重新计算哈希值后再插入即可;

每次下传标记的时候把哈希值相同的一段打上标记更新答案;

注意当交换的两个字符在同一个串中时要特殊处理,防止被删两次;

时间复杂度$O((l+logn)m)$

然而说起来很简单但我每次写平衡树都要调至少1h /微笑

代码:

 #include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<queue>
#define inf 2147483647
#define eps 1e-9
#define H 173
using namespace std;
typedef unsigned long long ll;
typedef double db;
struct node{
int son[],fa,siz;
}t[];
int n,l,m,x,y,a,b,rt,cnt=,ans[],tag[];
ll pw[],hs[];
char s[][];
bool Son(int u){
return t[t[u].fa].son[]==u;
}
void pushup(int u){
t[u].siz=t[t[u].son[]].siz+t[t[u].son[]].siz+;
}
void pd(int u){
if(tag[u]){
ans[t[u].son[]]=max(ans[t[u].son[]],tag[u]);
tag[t[u].son[]]=max(tag[t[u].son[]],tag[u]);
ans[t[u].son[]]=max(ans[t[u].son[]],tag[u]);
tag[t[u].son[]]=max(tag[t[u].son[]],tag[u]);
tag[u]=;
}
}
void rotate(int u){
int f=t[u].fa,ff=t[f].fa,ch=Son(u),cf=Son(f);
pd(f);
pd(u);
t[f].son[ch]=t[u].son[ch^];
t[t[f].son[ch]].fa=f;
t[ff].son[cf]=u;
t[u].son[ch^]=f;
t[u].fa=ff;
t[f].fa=u;
pushup(f);
pushup(u);
}
void splay(int u,int to){
for(;t[u].fa!=to;rotate(u)){
int f=t[u].fa;
if(t[f].fa!=to)rotate(Son(u)^Son(f)?u:f);
}
if(!to)rt=u;
}
int getpre(ll x){
int nw=rt,u=rt;
for(;nw;){
if(x>hs[nw]){
u=nw;
nw=t[nw].son[];
}else nw=t[nw].son[];
}
return u;
}
int getnxt(ll x){
int nw=rt,u;
for(;nw;){
if(x<hs[nw]){
u=nw;
nw=t[nw].son[];
}else nw=t[nw].son[];
}
return u;
}
int nxt(int u){
int nw=t[u].son[];
while(t[nw].son[])nw=t[nw].son[];
return nw;
}
void ins(int x){
int u=getpre(hs[x]),v=getnxt(hs[x]);
splay(u,);
splay(v,u);
t[x].son[]=t[v].son[];
t[t[x].son[]].fa=x;
t[v].son[]=x;
t[x].fa=v;
pushup(x);
pushup(v);
pushup(u);
ans[x]=max(ans[x],t[x].siz);
tag[x]=max(tag[x],t[x].siz);
}
void del(int x){
splay(x,);
int u=nxt(x);
splay(u,x);
rt=u;
t[u].son[]=t[x].son[];
t[t[u].son[]].fa=u;
t[u].fa=;
pushup(u);
t[x].son[]=t[x].son[]=;
t[x].siz=;
}
void dfs(int u){
pd(u);
if(t[u].son[])dfs(t[u].son[]);
if(t[u].son[])dfs(t[u].son[]);
}
int main(){
scanf("%d%d%d",&n,&l,&m);
pw[]=;
for(int i=;i<=l;i++)pw[i]=pw[i-]*H;
rt=n+;
t[rt].siz=;
hs[rt]=;
t[rt].son[]=n+;
t[n+].siz=;
t[n+].fa=rt;
hs[n+]=(1ll<<)-;
for(int i=;i<=n;i++){
scanf("%s",s[i]+);
for(int j=;j<=l;j++){
hs[i]=hs[i]*H+s[i][j];
}
ins(i);
}
for(int i=;i<=m;i++){
scanf("%d%d%d%d",&x,&a,&y,&b);
if(x==y){
del(x);
swap(s[x][a],s[x][b]);
hs[x]=;
for(int j=;j<=l;j++){
hs[x]=hs[x]*H+s[x][j];
}
ins(x);
}else{
del(x);
del(y);
swap(s[x][a],s[y][b]);
hs[x]=hs[y]=;
for(int j=;j<=l;j++){
hs[x]=hs[x]*H+s[x][j];
hs[y]=hs[y]*H+s[y][j];
}
ins(x);
ins(y);
}
}
dfs(rt);
for(int i=;i<=n;i++){
printf("%d\n",ans[i]);
}
return ;
}

【BZOJ1125】【POI2008】poc - splay+哈希的更多相关文章

  1. bzoj1125:[POI2008]Poc

    传送门 这个题好难卡啊. 看到这种题自然会想到字符串hash是不是,但是对于每次操作造成的影响需要\(O(n)\)的时间去更新,自然是不优的 可以发现这个更新可以用数据结构来维护,对于每个hash值开 ...

  2. 【BZOJ1125】[POI2008]Poc hash+map+SBT

    [BZOJ1125][POI2008]Poc Description n列火车,每条有l节车厢.每节车厢有一种颜色(用小写字母表示).有m次车厢交换操作.求:对于每列火车,在交换车厢的某个时刻,与其颜 ...

  3. BZOJ1014 JSOI2008火星人(splay+哈希)

    splay维护哈希值即可. #include<iostream> #include<cstdio> #include<cmath> #include<cstd ...

  4. bzoj 1014 [JSOI2008]火星人prefix——splay+哈希

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1014 用splay维护字符串,每个点记录子树的哈希值,然后二分查询. 二分不是把两个点的哈希 ...

  5. [POI2008] Poc (原名 Trians) Treap+Hash

    这个题和千山鸟飞绝体现出了一种用平衡树解决动态集合问题,主要套路就是蜜汁标记. 这个题我一开始用替罪羊树搞了一下对了28个点,后来我换成了Treap一搞对了14个点,再后来发现被卡了Hash我竟然在自 ...

  6. BZOJ1014火星人prefix Splay維護序列 + 字符串哈希

    @[Splay, 哈希] Description 火星人最近研究了一种操作:求一个字串两个后缀的公共前缀.比方说,有这样一个字符串:\(madamimadam\), 我们将这个字符串的各个字符予以标号 ...

  7. bzoj AC倒序

    Search GO 说明:输入题号直接进入相应题目,如需搜索含数字的题目,请在关键词前加单引号 Problem ID Title Source AC Submit Y 1000 A+B Problem ...

  8. [POI2008]KLO && POC

    题意:给定一个序列 s1, s2,...sn,以及一个k,求一个连续的k个数,把s[i]...s[i+k-1]变成一个数s',使得sigma(|s[j]-s'|)(i<=j<=i+k-1) ...

  9. 【BZOJ1014】火星人(Splay,哈希)

    [BZOJ1014]火星人(Splay,哈希) 题面 BZOJ 题解 要动态维护这个串,一脸的平衡树. 那么用\(Splay\)维护这个哈希值就好了. 每次计算答案的时候二分+Splay计算区间哈希值 ...

随机推荐

  1. WebApplicationContext初始化(转)

    ApplicationContext是Spring的核心,Context我们通常解释为上下文环境,我想用“容器”来表述它更容易理解一些,ApplicationContext则是“应用的容器”了:在We ...

  2. BIEE11G Rpd合并

    Rpd合并 如图,合并两个rpd须要用三个rpd文件来操作.一个是blank.rpd.这是一个空白rpd,在biee合并的时候作为"原始主资料档案库":另一个是modified.R ...

  3. python笔记:文件操作

    1.逐行打印整个文件 # -*- coding: utf-8 -*- f = open("test",'r',encoding="utf-8") count = ...

  4. openssl https证书

    今天摸索了下 HTTPS 的证书生成,以及它在 Nginx 上的部署.由于博客托管在 github 上,没办法部署证书,先记录下,后续有需要方便快捷操作.本文的阐述不一定完善,但是可以让一个初学者了解 ...

  5. cloudfoundry service broker 制作

    实验室这边需要制作service broker.从今天开始将精力投入其中.

  6. Several Ideas on Perl List Context

    According to Beginning Perl Book published by Tsinghua Pub., the list context appears when you are t ...

  7. 初学struts2杂乱笔记

    1.在web.xml文件里定义struts2里的一个过滤类org.apache.struts2.dispatcher.FilterDispatcher 2.在src目录下创建struts.xml文件, ...

  8. 数据库表结构导出sql语句

    在“对象资源管理器”中找到要导出的表,选中该表并单击右键,“编写表脚本为(S)”/“CREATE到(C)”/“新查询编辑器窗口”即可查看该表的建表语句,Ctrl+S保存为sql脚本文件

  9. webpack打包大概流程

    webpack 步骤 1. 新建一个webpack.config.prod.js 2. 压缩bundle.js和index.html //设置为生产环境 new webpack.DefinePlugi ...

  10. 图片文字滚动插件jQuery Scrollbox

    图片文字滚动插件jQuery Scrollbox附件中提供了五种图片.文字滚动样式,只需调用jquery库和jQuery Scrollbox插件,然后再加一段简单的jquery代码即可使用,兼容性良好 ...