码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2014-10-19 15:29:13      阅读:199      评论:0      收藏:0      [点我收藏+]

标签:style   blog   color   io   os   ar   for   strong   sp   

每个房间用一个集合来维护,具体来说,就是给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 }

 

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

标签:style   blog   color   io   os   ar   for   strong   sp   

原文地址:http://www.cnblogs.com/autsky-jadek/p/4034867.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!