【分块】【哈希】bzoj3578 GTY的人类基因组计划2
每个房间用一个集合来维护,具体来说,就是给1-n的数每个数一个long long的hash值,往集合S里insert(i),就是S^=HASH[i];erase(i),也是S^=HASH[i]。
用map/set维护某个集合是否已经做过实验。
分块,对每个块维护一个maxv[i],代表当前该块内的答案值,要注意,若某个房间的集合的vis[S[i]]==true,则它对其所在块没有贡献。
分块相对于线段树/平衡树/树套树的很大的好处,就是思路简单暴力,代码短,常数小,应对范围广,可以方便地扩张。
像这种区间修改的问题,可以类比线段树打懒标记的思路来进行,使得每次修改是O(sqrt(n))的。
Pushdown函数需要每次对块进行“零散地”操作的之前进行。
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstdlib>
#include<ctime>
#include<map>
using namespace std;
unsigned long long HASH[];
struct SET
{
unsigned long long S;int size;
void insert(const int &v){S^=HASH[v];size++;}
void erase(const int &v){S^=HASH[v];size--;}
};
int n,m,q,l[],r[],sumv[],sum,sz,num[],x,y,pos[];
bool delta[];
SET sets[];
map<unsigned long long,bool>vis;
char op[];
int Res,Num;char C,CH[];
inline int G()
{
Res=;C='*';
while(C<''||C>'')C=getchar();
while(C>=''&&C<=''){Res=Res*+(C-'');C=getchar();}
return Res;
}
inline void P(long long x)
{
Num=;if(!x){putchar('');puts("");return;}
while(x>)CH[++Num]=x%,x/=;
while(Num)putchar(CH[Num--]+);
puts("");
}
void makeblock()
{
srand();
for(int i=;i<=n;i++) HASH[i]=(unsigned long long)((unsigned long long)rand()<<)|((unsigned long long)rand()<<)|((unsigned long long)rand()<<)|((unsigned long long)rand());
sz=sqrt((double)m*0.3);
for(int i=;i<=n;i++) {sets[].insert(i); pos[i]=;}
sumv[]=n;
for(sum=;sum*sz<m;sum++)
{
l[sum]=(sum-)*sz+;
r[sum]=sum*sz;
for(int i=l[sum];i<=r[sum];i++) num[i]=sum;
}
l[sum]=sz*(sum-)+; r[sum]=m;
for(int i=l[sum];i<=r[sum];i++) num[i]=sum;
}
inline void Pushdown(const int &p)//对块p下传标记,Pushdown操作需要每次对块进行零散操作之前进行
{
if(delta[p])
{
for(int i=l[p];i<=r[p];i++)
if(sets[i].size)
vis[sets[i].S]=true;
delta[p]=false;
}
}
inline void Move()
{
Pushdown(num[pos[x]]);
bool flag1=vis[sets[pos[x]].S];
sets[pos[x]].erase(x);
bool flag2=vis[sets[pos[x]].S];
if(flag1&&!flag2) sumv[num[pos[x]]]+=sets[pos[x]].size;
else if(!flag1&&flag2) sumv[num[pos[x]]]-=(sets[pos[x]].size+);
else if(!flag1&&!flag2) sumv[num[pos[x]]]--;
Pushdown(num[y]);
flag1=vis[sets[y].S];
sets[y].insert(x);
flag2=vis[sets[y].S];
if(flag1&&!flag2) sumv[num[y]]+=sets[y].size;
else if(!flag1&&flag2) sumv[num[y]]-=(sets[y].size-);
else if(!flag1&&!flag2) sumv[num[y]]++;
pos[x]=y;
}
inline void Update_Query()
{
int ans=;
Pushdown(num[x]);
Pushdown(num[y]);
if(num[x]+>=num[y])
{
for(int i=x;i<=y;i++)
if(sets[i].size)
if(!vis[sets[i].S])
{
ans+=sets[i].size;
sumv[num[i]]-=sets[i].size;
vis[sets[i].S]=true;
}
}
else
{
for(int i=x;i<=r[num[x]];i++)
if(sets[i].size)
if(!vis[sets[i].S])
{
ans+=sets[i].size;
sumv[num[x]]-=sets[i].size;
vis[sets[i].S]=true;
}
for(int i=l[num[y]];i<=y;i++)
if(sets[i].size)
if(!vis[sets[i].S])
{
ans+=sets[i].size;
sumv[num[y]]-=sets[i].size;
vis[sets[i].S]=true;
}
for(int i=num[x]+;i<num[y];i++)
{
if(!delta[i])
ans+=sumv[i];
delta[i]=true;
sumv[i]=;
}
}
P(ans);
}
int main()
{
n=G();m=G();q=G();
makeblock();
for(;q>;q--)
{
scanf("%s",op);x=G();y=G();
if(op[]=='C') Move();
else Update_Query();
}
return ;
}
【分块】【哈希】bzoj3578 GTY的人类基因组计划2的更多相关文章
- BZOJ3578:GTY的人类基因组计划2(集合hash,STL)
Description GTY召唤了n个人来做实验,GTY家的房子很大,有m个房间一开始所有人都在1号房间里,GTY会命令某人去某个房间等待做实验,或者命令一段区间的房间开始实验,实验会获得一些实验信 ...
- BZOJ3578 : GTY的人类基因组计划2
关于如何判断一个集合是否出现过: 给每个元素随机一个hash权值,然后xor起来即可 插入删除都只需xor 线段树维护区间有效人数和,以及打标记表示这个区间的集合要全部标记为出现过,并把区间内sum值 ...
- 【BZOJ-3578】GTY的人类基因组计划2 set + map + Hash 乱搞
3578: GTY的人类基因组计划2 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 367 Solved: 159[Submit][Status][ ...
- HDU 4391 - Paint The Wall - 分块哈希入门
题目链接 : http://acm.hdu.edu.cn/showproblem.php?pid=4391 题意 : 给一段区间, 有两种操作 1 : 给 x 到 y 的区间染色为 z 2 : 查询 ...
- Codeforces 1340F - Nastya and CBS(分块+哈希)
Codeforces 题面传送门 & 洛谷题面传送门 首先看到这样的数据范围我们可以考虑分块,具体来说,对于每一块我们记录其中的括号是否能完全消掉,以及对其进行括号相消之后的括号序列(显然是一 ...
- NOIP2018 - 暑期博客整理
暑假写的一些博客复习一遍.顺便再写一遍或者以现在的角度补充一点东西. 盛暑七月 初涉基环外向树dp&&bzoj1040: [ZJOI2008]骑士 比较经典的基环外向树dp.可以借鉴的 ...
- bzoj AC倒序
Search GO 说明:输入题号直接进入相应题目,如需搜索含数字的题目,请在关键词前加单引号 Problem ID Title Source AC Submit Y 1000 A+B Problem ...
- CHAPTER 38 Reading ‘the Book of Life’ The Human Genome Project 第38章 阅读生命之书 人体基因组计划
CHAPTER 38 Reading ‘the Book of Life’ The Human Genome Project 第38章 阅读生命之书 人体基因组计划 Humans have about ...
- AI-Info-Micron:人如其食:人工智能和人类微生物组
ylbtech-AI-Info-Micron:人如其食:人工智能和人类微生物组 1.返回顶部 1. 人如其食:人工智能和人类微生物组 “相信你身体发出的信号”,的确是一个很好的建议.研究人员在不遗余力 ...
随机推荐
- 深入理解Java虚拟机—内存管理机制
前面说过了类的加载机制,里面讲到了类的初始化中时用到了一部分内存管理的知识,这里让我们来看下Java虚拟机是如何管理内存的. 先让我们来看张图 有些文章中对线程隔离区还称之为线程独占区,其实是一个意思 ...
- E. Intercity Travelling
E. Intercity Travelling time limit per test 1.5 seconds memory limit per test 256 megabytes input st ...
- [Python]简单的外星人入侵游戏
alien_invasion.py: import sys import pygame from setting import Settings from ship import Ship impor ...
- js错误处理
导致程序无法继续执行的异常状态称为错误. js中一旦发生错误,就会自动创建一个Error类型对象 js中有6中错误类型: SyntaxError 语法错误 ReferenceError 引用错误,找不 ...
- OOP第三次上机
上机问题 T1 CSet 还是熟悉的CSet,只是多了个构造函数以及收缩空间. T2 SingleTon 单例问题. 用一个指针保存唯一的实例,用户无法在外部直接新建实例,只能使用外部接口(函数),函 ...
- [bzoj4602][Sdoi2016]齿轮——dfs
题目 现有一个传动系统,包含了N个组合齿轮和M个链条.每一个链条连接了两个组合齿轮u和v,并提供了一个传动比x : y.即如果只考虑这两个组合齿轮,编号为u的齿轮转动x圈,编号为v的齿轮会转动y圈.传 ...
- [bzoj3876][AHOI2014]支线剧情——上下界费用流
题目 传送门 题解 建立s和t,然后s向1连下限0上限inf费用0的边,除1外所有节点向t连下限0上限inf费用0的边,对于每条边下限为1上限为inf费用为经过费用,然后我们只有做上下界网络流构出新图 ...
- LeetCode189:Rotate Array
Rotate an array of n elements to the right by k steps. For example, with n = 7 and k = 3, the array ...
- Manipulating Files
http://linuxcommand.org/lc3_lts0050.php This lesson will introduce you to the following commands: cp ...
- unixbench安装使用
UnixBench是一个类unix系(Unix,BSD,Linux)统下的性能测试工具,一个开源工具,被广泛用与测试linux系统主机的性能.Unixbench的主要测试项目有:系统调用.读写.进程. ...