CF707D Persistent Bookcase 可持久化线段树
维护一个二维零一矩阵(n,m<=1000),支持四种操作(不超过10^5次):
- 将(i,j)置一
- 将(i,j)置零
- 将第i行零一反转yu
- 回到第K次操作前的状态
- 每次操作后输出全局一共有多少个一
你发现如果每一次操作都复制一整行的话是可以用 $bitset$ 优化的,自带/32
所以,我们对于每一个时刻维护一个线段树,其中 $i$ 节点表示第 $i$ 行对应的 $bitset$ 编号.
对于前 $3$ 个操作,每一次操作时都暴力新建一个 bitset,然后每次在可持久化线段树上最多更新一个单点.
顺便在线段树的节点上再维护一个 $1$ 的数量即可.
#include <bits/stdc++.h>
#define M 1004
#define N 100005
#define setIO(s) freopen(s".in","r",stdin) , freopen(s".out","w",stdout)
using namespace std;
bitset<M>v[N],uni,oo;
int rt[N];
namespace seg
{
#define lson t[x].ls
#define rson t[x].rs
int tot;
int newnode() { return ++ tot; }
struct Node
{
int ls,rs,id,sum;
}t[N*40];
int update(int x,int l,int r,int p,int v)
{
int now=newnode();
t[now]=t[x];
if(l==r)
{
t[now].id=v;
return now;
}
int mid=(l+r)>>1;
if(p<=mid)
{
t[now].ls=update(lson,l,mid,p,v);
}
else
{
t[now].rs=update(rson,mid+1,r,p,v);
}
t[now].sum=t[t[now].ls].sum+t[t[now].rs].sum;
return now;
}
int modify(int x,int l,int r,int p,int v)
{
int now=newnode();
t[now]=t[x];
if(l==r)
{
t[now].sum=v;
return now;
}
int mid=(l+r)>>1;
if(p<=mid) t[now].ls=modify(lson,l,mid,p,v);
else t[now].rs=modify(rson,mid+1,r,p,v);
t[now].sum=t[t[now].ls].sum+t[t[now].rs].sum;
return now;
}
int query(int x,int l,int r,int p)
{
if(!x) return 0;
if(l==r) return t[x].id;
int mid=(l+r)>>1;
if(p<=mid) return query(lson,l,mid,p);
else return query(rson,mid+1,r,p);
}
void dfs(int x,int l,int r)
{
if(!x) return;
if(l==r) printf("%d %d\n",l,t[x].sum);
int mid=(l+r)>>1;
dfs(lson,l,mid), dfs(rson,mid+1,r);
}
#undef lson
#undef rson
};
int main()
{
// setIO("now");
int n,m,q,i,j;
scanf("%d%d%d",&n,&m,&q);
for(i=1;i<=m;++i) uni[i]=1;
for(i=1;i<=q;++i)
{
int op,a,b,c;
scanf("%d",&op);
rt[i]=rt[i-1];
if(op==1)
{
scanf("%d%d",&a,&b);
int pre=seg::query(rt[i-1],1,n,a);
v[i]=v[pre];
v[i][b]=1;
rt[i]=seg::update(rt[i-1],1,n,a,i);
oo=v[i]&uni;
rt[i]=seg::modify(rt[i],1,n,a,oo.count());
}
if(op==2)
{
scanf("%d%d",&a,&b);
int pre=seg::query(rt[i-1],1,n,a);
v[i]=v[pre];
v[i][b]=0;
rt[i]=seg::update(rt[i-1],1,n,a,i);
oo=v[i]&uni;
rt[i]=seg::modify(rt[i],1,n,a,oo.count());
}
if(op==3)
{
int x;
scanf("%d",&x);
int pre=seg::query(rt[i-1],1,n,x);
v[i]=v[pre]^uni;
rt[i]=seg::update(rt[i-1],1,n,x,i);
oo=v[i]&uni;
rt[i]=seg::modify(rt[i],1,n,x,oo.count());
}
if(op==4)
{
int x;
scanf("%d",&x);
rt[i]=rt[x];
}
printf("%d\n",seg::t[rt[i]].sum);
}
return 0;
}
CF707D Persistent Bookcase 可持久化线段树的更多相关文章
- CF707D Persistent Bookcase
CF707D Persistent Bookcase 洛谷评测传送门 题目描述 Recently in school Alina has learned what are the persistent ...
- PYOJ 44. 【HNSDFZ2016 #6】可持久化线段树
#44. [HNSDFZ2016 #6]可持久化线段树 统计 描述 提交 自定义测试 题目描述 现有一序列 AA.您需要写一棵可持久化线段树,以实现如下操作: A v p x:对于版本v的序列,给 A ...
- 【BZOJ-3673&3674】可持久化并查集 可持久化线段树 + 并查集
3673: 可持久化并查集 by zky Time Limit: 5 Sec Memory Limit: 128 MBSubmit: 1878 Solved: 846[Submit][Status ...
- 【BZOJ-2653】middle 可持久化线段树 + 二分
2653: middle Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 1298 Solved: 734[Submit][Status][Discu ...
- HDU 4866 Shooting(持久化线段树)
view code//第二道持久化线段树,照着别人的代码慢慢敲,还是有点不理解 #include <iostream> #include <cstdio> #include & ...
- 【BZOJ-3653】谈笑风生 DFS序 + 可持久化线段树
3653: 谈笑风生 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 628 Solved: 245[Submit][Status][Discuss] ...
- 【BZOJ3673】&&【BZOJ3674】: 可持久化并查集 by zky 可持久化线段树
没什么好说的. 可持久化线段树,叶子节点存放父亲信息,注意可以规定编号小的为父亲. Q:不是很清楚空间开多大,每次询问父亲操作后修改的节点个数是不确定的.. #include<bits/stdc ...
- 【BZOJ3207】花神的嘲讽计划I 可持久化线段树/莫队
看到题目就可以想到hash 然后很自然的联想到可持久化权值线段树 WA:base取了偶数 这道题还可以用莫队做,比线段树快一些 可持久化线段树: #include<bits/stdc++.h&g ...
- 【BZOJ 3674】可持久化并查集加强版&【BZOJ 3673】可持久化并查集 by zky 用可持久化线段树破之
最后还是去掉异或顺手A了3673,,, 并查集其实就是fa数组,我们只需要维护这个fa数组,用可持久化线段树就行啦 1:判断是否属于同一集合,我加了路径压缩. 2:直接把跟的值指向root[k]的值破 ...
随机推荐
- PAT(B) 1093 字符串A+B(Java和C)
题目链接:1093 字符串A+B (20 point(s)) 题目描述 给定两个字符串 A 和 B,本题要求你输出 A+B,即两个字符串的并集.要求先输出 A,再输出 B,但重复的字符必须被剔除. 输 ...
- PAT(B) 1081 检查密码(Java)
题目链接:1081 检查密码 (15 point(s)) 题目描述 本题要求你帮助某网站的用户注册模块写一个密码合法性检查的小功能.该网站要求用户设置的密码必须由不少于6个字符组成,并且只能有英文字母 ...
- Python开发【第二章】:模块和运算符
一.模块初识: Python有大量的模块,从而使得开发Python程序非常简洁.类库有包括三中: Python内部提供的模块 业内开源的模块 程序员自己开发的模块 1.Python内部提供一个 sys ...
- 用.net4中的DynamicObject实现简单AOP
public class DynamicWrapper : DynamicObject { private readonly object source; public DynamicWrapper( ...
- 【转载】 C#使用string.Join快速用特定字符串串联起数组
在C#中有时候我们的数组元素需要通过一些特定的字符串串联起来,例如将整形Int数组通过逗号快速串联起来成为一个字符串,可以使用String.Join方法.或者一个字符串string类型数组所有元素快速 ...
- 关于Vue中,父组件获取子组件的数据(子组件调用父组件函数)的方法
1. 父组件调用子组件时,在调用处传给子组件一个方法 :on-update="updateData" 2. 子组件在props中,接收这个方法并声明 props: { onUp ...
- K2 BPM_规范内部供应链流程,提高企业整体绩效_工作流流程管理
方案背景 随着企业竞争的加剧.顾客需求的多样化以及市场变化的不确定因素增多,企业与企业间的竞争已经逐步转变为供应链与供应链间的竞争.企业只有在内部各业务流程有机统一的状态下,再与外部企业进行融合与协作 ...
- shell 文本处理三剑客之 grep 和 egrep
shell 三剑客之 grep 命令语法格式 grep 参数 案例 显示file中有python的行 grep python file 显示没有python的行,不忽略大小写 grep -v pyth ...
- 15 Windows编程——系统内置窗口子类型之button
button子类型BS_3STATE.BS_AUTO3STATE.BS_AUTOCHECKBOX 源码 #include<Windows.h> #include<Windowsx.h ...
- HTML中使用图像
插入图像 在页面中插入图像的标记只有一个,就是img标记. 语法为:<img src="图片地址" alt="下载失败时的替换文本" title='提示文 ...