题意:

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. 第二次训练 密码acmore

    网址:http://acm.hust.edu.cn/vjudge/contest/view.action?cid=26733#overview 贪心全场!!!! A题: #include <io ...

  2. hdu 1713求分数的最小公倍数

    题意中的圈数和天数说反了 #include<stdio.h> __int64 gcd(__int64 a,__int64 b) {/* 比如4/3 3/5 通分20/15 9/15 所以这 ...

  3. spring boot下接口调用失败重试方案

    背景: 在项目开发中,有时候会出现接口调用失败,本身调用又是异步的,如果是因为一些网络问题请求超时,总想可以重试几次把任务处理掉. 一些RPC框架,比如dubbo都是有重试机制的,但是并不是每一个项目 ...

  4. POJ 1985

    求一棵树内最远的两点,DFS,顺便记录以某节点为根内最远的两点的距离,返回最远点的距离.其实是DP. #include <cstdio> #include <iostream> ...

  5. Rails 异常处理 &amp;&amp; 性能

    Rails 异常处理 的多种处理方法 1.  routes match '*path', via: :all, to: 'controller#action' 2.  application.rb 的 ...

  6. [剑指offer]Q13:O(1)时间删除链表的结点

    通常我们所说的删除链表的某个结点,是彻底删除该结点的空间.而要这么做就必须知道其前驱结点.这里的想法是,链表中存储的val是同类型的,仅仅要将该结点的val内容删除就能够了. 那么就能够用该结点的后继 ...

  7. JS清除选择内容的方法

    本文实例讲述了JS清除选择内容的方法.分享给大家供大家参考.具体分析如下: 今天在做一个DIV拖动的效果,发现在拖动的时候会选中页面中的文本,于是找了一下JS清除选择的内容的相关信息. 在得到的结果中 ...

  8. 扩展欧几里德 poj1061 青蛙的约会

    扩展欧几里德很经典.可是也有时候挺难用的.一些东西一下子想不明确.. 于是来了一个逆天模板..仅仅要能列出Ax+By=C.就能解出x>=bound的一组解了~ LL exgcd(LL a, LL ...

  9. Unity3d数据加密

    在unity中能够使用c#自带的对称算法对数据进行加密,以下两种加密算法: using System; using System.Text; using System.Security.Cryptog ...

  10. CSS学习(十六)-HSLA颜色模式

    一.理论: 1.HSLA颜色模式 a.HSLA在HSL基础上添加了不透明度,值越大透明度越低 b.HSLA颜色模式的浏览器兼容性和HSL一样,仅仅有较新版本号的主流浏览器才支持 2.RGBA和HSLA ...