【分块】【哈希】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. 人如其食:人工智能和人类微生物组 “相信你身体发出的信号”,的确是一个很好的建议.研究人员在不遗余力 ...
随机推荐
- POJ3189:Steady Cow Assignment(二分+二分图多重匹配)
Steady Cow Assignment Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 7482 Accepted: ...
- JAVA多线程---好的博客资源收集
个人笔记,备忘 1.http://blog.csdn.net/column/details/concurrency.html 兰亭风雨的专栏 2.http://lavasoft.blog.51c ...
- 创建Maven项目出现:An internal error occurred during: "Retrieving archetypes:". Java heap space 错误解决办法
首先说明一下网上的方法: 在Eclipse中创建Maven的Web项目时出现错误:An internal error occurred during: "Retrieving archety ...
- win 7 64 位系统驱动签名
自己开发未经签名的驱动无法加载,关闭Windows 7系统中的驱动签名强制要求 bcdedit.exe -set loadoptions DDISABLE_INTEGRITY_CHECKS
- UOJ#80 二分图最大权匹配 [模板题]
从前一个和谐的班级,有 nlnl 个是男生,有 nrnr 个是女生.编号分别为 1,…,nl1,…,nl 和 1,…,nr1,…,nr. 有若干个这样的条件:第 vv 个男生和第 uu 个女生愿意结为 ...
- #学习方法2打印为空,说明#延迟加载#解决方案:将nameField等设置改在viewDidLoad中设置
#学习方法#error调试#NSLog调试之无法进行数据传输,Edit无法现实之前编辑 的内容 https://www.evernote.com/shard/s227/sh/c ...
- select实现斐波那契和超时机制
package main import "fmt" func fib(ch chan <-int, quit <- chan bool){ x, y := 1, 1 f ...
- 在react项目中使用ECharts
这里我们要在自己搭建的react项目中使用ECharts,我们可以在ECharts官网上看到有一种方式是在 webpack 中使用 ECharts,我们需要的就是这种方法. 我们在使用ECharts之 ...
- selenium TestNG 依赖和忽略测试
依赖:通过使用Test 注释的dependsOnMethods={"verifyLogin"}子句,verifyAccountInfo 测试指定了它依赖verifyLogin()方 ...
- PHP文件环境搭建—EcShop环境搭建
1 rpm -qa|grep yum|xargs rpm -e --nodeps 2 ls 3 rpm -ivh python-iniparse-0.3.1-2.1.el6.noar ...