【分块】【哈希】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函数需要每次对块进行“零散地”操作的之前进行。

  1 #include<cstdio>
  2 #include<cmath>
  3 #include<algorithm>
  4 #include<cstdlib>
  5 #include<ctime>
  6 #include<map>
  7 using namespace std;
  8 unsigned long long HASH[100001];
  9 struct SET
 10 {
 11     unsigned long long S;int size;
 12     void insert(const int &v){S^=HASH[v];size++;}
 13     void erase(const int &v){S^=HASH[v];size--;}
 14 };
 15 int n,m,q,l[600],r[600],sumv[600],sum,sz,num[100001],x,y,pos[100001];
 16 bool delta[600];
 17 SET sets[100001];
 18 map<unsigned long long,bool>vis;
 19 char op[1];
 20 int Res,Num;char C,CH[12];
 21 inline int G()
 22 {
 23     Res=0;C=‘*‘;
 24     while(C<‘0‘||C>‘9‘)C=getchar();
 25     while(C>=‘0‘&&C<=‘9‘){Res=Res*10+(C-‘0‘);C=getchar();}
 26     return Res;
 27 }
 28 inline void P(long long x)
 29 {
 30     Num=0;if(!x){putchar(‘0‘);puts("");return;}
 31     while(x>0)CH[++Num]=x%10,x/=10;
 32     while(Num)putchar(CH[Num--]+48);
 33     puts("");
 34 }
 35 void makeblock()
 36 {
 37     srand(233);
 38     for(int i=1;i<=n;i++) HASH[i]=(unsigned long long)((unsigned long long)rand()<<48)|((unsigned long long)rand()<<32)|((unsigned long long)rand()<<16)|((unsigned long long)rand());
 39     sz=sqrt((double)m*0.3);
 40     for(int i=1;i<=n;i++) {sets[1].insert(i); pos[i]=1;}
 41     sumv[1]=n;
 42     for(sum=1;sum*sz<m;sum++)
 43       {
 44         l[sum]=(sum-1)*sz+1;
 45         r[sum]=sum*sz;
 46         for(int i=l[sum];i<=r[sum];i++) num[i]=sum;
 47       }
 48     l[sum]=sz*(sum-1)+1; r[sum]=m;
 49     for(int i=l[sum];i<=r[sum];i++) num[i]=sum;
 50 }
 51 inline void Pushdown(const int &p)//对块p下传标记,Pushdown操作需要每次对块进行零散操作之前进行
 52 {
 53     if(delta[p])
 54       {
 55           for(int i=l[p];i<=r[p];i++)
 56           if(sets[i].size)
 57             vis[sets[i].S]=true;
 58         delta[p]=false;
 59       }
 60 }
 61 inline void Move()
 62 {
 63     Pushdown(num[pos[x]]);
 64     bool flag1=vis[sets[pos[x]].S];
 65     sets[pos[x]].erase(x);
 66     bool flag2=vis[sets[pos[x]].S];
 67     if(flag1&&!flag2) sumv[num[pos[x]]]+=sets[pos[x]].size;
 68     else if(!flag1&&flag2) sumv[num[pos[x]]]-=(sets[pos[x]].size+1);
 69     else if(!flag1&&!flag2) sumv[num[pos[x]]]--;
 70     Pushdown(num[y]);
 71     flag1=vis[sets[y].S];
 72     sets[y].insert(x);
 73     flag2=vis[sets[y].S];
 74     if(flag1&&!flag2) sumv[num[y]]+=sets[y].size;
 75     else if(!flag1&&flag2) sumv[num[y]]-=(sets[y].size-1);
 76     else if(!flag1&&!flag2) sumv[num[y]]++;
 77     pos[x]=y;
 78 }
 79 inline void Update_Query()
 80 {
 81     int ans=0;
 82     Pushdown(num[x]);
 83     Pushdown(num[y]);
 84     if(num[x]+1>=num[y])
 85       {
 86         for(int i=x;i<=y;i++)
 87           if(sets[i].size)
 88             if(!vis[sets[i].S])
 89               {
 90                   ans+=sets[i].size;
 91                   sumv[num[i]]-=sets[i].size;
 92                 vis[sets[i].S]=true;
 93               }
 94       }
 95     else
 96       {
 97           for(int i=x;i<=r[num[x]];i++)
 98             if(sets[i].size)
 99             if(!vis[sets[i].S])
100               {
101                   ans+=sets[i].size;
102                   sumv[num[x]]-=sets[i].size;
103                 vis[sets[i].S]=true;
104               }
105           for(int i=l[num[y]];i<=y;i++)
106             if(sets[i].size)
107             if(!vis[sets[i].S])
108               {
109                   ans+=sets[i].size;
110                   sumv[num[y]]-=sets[i].size;
111                 vis[sets[i].S]=true;
112               }
113           for(int i=num[x]+1;i<num[y];i++)
114           {
115             if(!delta[i])
116               ans+=sumv[i];
117             delta[i]=true;
118             sumv[i]=0;
119           }
120       }
121     P(ans);
122 }
123 int main()
124 {
125     n=G();m=G();q=G();
126     makeblock();
127     for(;q>0;q--)
128       {
129           scanf("%s",op);x=G();y=G();
130           if(op[0]==‘C‘) Move();
131           else Update_Query();
132       }
133     return 0;
134 }
时间: 2024-11-09 10:48:48

【分块】【哈希】bzoj3578 GTY的人类基因组计划2的相关文章

BZOJ3578 GTY的人类基因组计划2 HASH

题意:有N个人M个房间,初始时所有人都在1号房间,维护:1.让某个人去某个房间  2.假如[l,r]中所有的人还未一起统计过,Ans+=人数.输出Ans 题解: 集合HASH get 根据异或的性质,a^x^x=a,因此一个集合的HASH值就是其所有元素的异或起来的值 接下来就是STL大法好 将每个房间看成一个集合,每个人赋一个初始rand,set存储当前所有HASH值没有出现过的房间.对于每个询问,二分出所有区间之间的房间,统计答案即可. #include <set> #include &l

【BZOJ-3578】GTY的人类基因组计划2 set + map + Hash 乱搞

3578: GTY的人类基因组计划2 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 367  Solved: 159[Submit][Status][Discuss] Description GTY召唤了n个人来做实验,GTY家的房子很大,有m个房间一开始所有人都在1号房间里,GTY会命令某人去某个房间等待做实验,或者命令一段区间的房间开始实验,实验会获得一些实验信息点数,点数为房间里的人数,如果一个房间里的一群人已经做过实验了那么这些人将不会增

BZOJ 3578 GTY的人类基因组计划2 set

题目大意:有一些人一开始都在一号房间.有一些指令使他们区别的房间.每次选定一段区间作试验,如果有的房间的组合已经做过试验,那么就不计入最后的试验点数,否则计入试验点数为试验的人数.问最后会获得多少试验点数. 思路:对于每一个人随即一个long long,一个集合所代表的数字就是这些long long的异或和.然后用set来暴力判重. CODE: #include <set> #include <cstdio> #include <cstring> #include &l

HDU 4391 - Paint The Wall - 分块哈希入门

题目链接 : http://acm.hdu.edu.cn/showproblem.php?pid=4391 题意 : 给一段区间, 有两种操作 1 : 给 x 到 y 的区间染色为 z 2 : 查询 x 到 y 的区间内颜色z的数目 思路 : 这题的z最大2^31-1, 区间长度最大1e5, 用线段树将颜色离散化之后维护也存不下 所以用分块哈希, 将一个长度为n的区间分为sqrt(n)块分块维护, 每一块中都用map记录某些颜色的个数 分块哈希 : 修改, 查询一段区间, 对于完整覆盖到的区间,

让工程科技造福人类、创造未来—在2014年国际工程科技大会上的主旨演讲

在2014国际工程科技大会发表主旨演讲 女士们,先生们,朋友们: 在这个美好的时节,国际工程科技大会在北京隆重召开,这是世界工程科技界和中国工程科技界的一件盛事.我很高兴有机会同来自世界各地的工程科技专家学者见面,也很愿意聆听大家对工程科技发展.人类社会未来的高见. 首先,我谨代表中国政府和中国人民,并以我个人的名义,向大会的召开,表示衷心的祝贺!向出席大会的全体代表,表示诚挚的欢迎!向国际工程与技术科学院理事会会议的召开,表示衷心的祝贺! 工程科技与人类生存息息相关.温故而知新.回顾人类文明历

国际人类蛋白质组计划

国际人类蛋白质组计划(HPP)是继国际人类基因组计划之后的又一项大规模的国际性科技工程.首批行动计划包括由中国科学家牵头的“人类肝脏蛋白质组计划”和美国科学家牵头的“人类血浆蛋白质组计划”.“人类肝脏蛋白质组计划”的总部设在中国首都北京,这是中国科学家第一次领导执行重大国际科技协作计划. 中文名 外文名 HPP 性    质 国际性科技工程 特    点 第一次领导执行国际科技计划 完成时间 2003年4月 耗费时间 13年 目录 1启动 2进展 3项目 4前景 5大事记 1启动 2003年4月

AI-Info-Micron:人如其食:人工智能和人类微生物组

ylbtech-AI-Info-Micron:人如其食:人工智能和人类微生物组 1.返回顶部 1. 人如其食:人工智能和人类微生物组 “相信你身体发出的信号”,的确是一个很好的建议.研究人员在不遗余力地向我们展示,我们体内的肠胃等器官状态对我们的生活质量有着具有巨大且往往看不见的影响. 消化道和皮肤上的细菌.真菌.病毒和原生动物被称为微生物群系或微生物组,会对我们的健康.福祉.情绪.寿命甚至体重产生重大影响.微生物组研究人员认为,就人类生命而言,微生物组扮演的角色可能与 DNA 同等重要. 微生

Science综述 | 用单细胞基因组学将人类细胞表型匹配到基因型

原文地址:https://science.sciencemag.org/content/365/6460/1401 <更多精彩,可关注微信公众号:AIPuFuBio,和大型免费综合生物信息学资源和工具平台AIPuFu:www.aipufu.com> Mapping human cell phenotypes to genotypes with single-cell genomics 摘要 身体所有细胞的累积活动,以及它们无数的相互作用.存亡历程和环境变化,产生了人类个体特有的性状.对人类细胞

弗拉特利定律:Illumina如何缔造基因革命

蕾妮·瓦林特(Renee Valint)的女儿谢尔碧(Shelby)在2000年出生时,看起来虚弱无力,就如同一只耷拉着的布娃娃.谢尔碧学着走路和说话,但学得非常慢,错过了儿童发展的重要阶段.到4岁时,她还只能坐在轮椅上.到五年级时,她开始要用电子语音设备与人交流.绝望无助的蕾妮把女儿从菲尼克斯带到明尼苏达州罗切斯特的梅奥诊所(Mayo Clinic),进行最后一周的检查,并与美国最好的一些医生讨论病情. "他们都把手一摊,说:'我们不知道她出了什么问题.'"蕾妮说道,"那时