zoukankan      html  css  js  c++  java
  • HDU 4391 Paint The Wall [分块哈希]

      给出一个区间以及两种区间操作,[1 l,r,c]把l~r的点染成c色,[2,l,r,c]查询l~r内颜色为c的点的数目。

      因为c的数目太大,用线段树是存不下的,所以只能另辟蹊径了。虽然网上有线段树的方法,但那个Max-Min剪枝完全是没有作用的,随便出一组数据,把所有点间隔染成3,5,然后查4,这样用线段树不知道要跑多久。。。

      题解说这题是裸的分块HASH。。还没写过,学习了。其实就是将原区间划分乘sqrt(n)个区间,每次暴力查询和跟新两边的区间,中间的区间直接用hash存每种颜色的节点的数量。这里用到了类似线段树的lazy思想,区间成段修改直接打个标记,等到要划分这个区间的时候先把标记传下去,然后跟新。

      复杂度可以保证在每次操作sqrt(n)左右,这里为了方便我就直接写map了。。

      

     1 #include <stdio.h>
     2 #include <math.h>
     3 #include <string.h>
     4 #include <map>
     5 #define MAXN 100005
     6 int n,m,bsize,bnum,x[MAXN];
     7 struct hash_block{
     8      int cls,size;
     9      std::map<int,int> mp;
    10 }b[350];
    11 //下传标记,当这个块化整为零的时候需要下传标记并跟新所有元素
    12 void pushdown(int id){
    13     hash_block &hb=b[id];
    14     if(hb.cls!=-1){
    15         for(int i=id*bsize;i<id*bsize+hb.size;i++)x[i]=hb.cls;
    16         hb.mp.clear(),hb.mp[hb.cls]=hb.size;
    17         hb.cls=-1;
    18     }
    19 }
    20 //跟新,中间的部分打标记就可以了,两边的sqrt(n)暴力跟新
    21 void update(int l,int r,int c){
    22     int lb=l/bsize,rb=r/bsize,ans=0;
    23     for(int i=lb+1;i<rb;i++)b[i].cls=c;
    24     if(lb!=rb){
    25         pushdown(lb);pushdown(rb);
    26         for(int i=l;i<lb*bsize+b[lb].size;i++)
    27             b[lb].mp[x[i]]--,b[lb].mp[c]++,x[i]=c;
    28         for(int i=rb*bsize;i<=r;i++)
    29             b[rb].mp[x[i]]--,b[rb].mp[c]++,x[i]=c;
    30     }else{
    31     pushdown(lb);
    32     for(int i=l;i<=r;i++)
    33         b[lb].mp[x[i]]--,b[lb].mp[c]++,x[i]=c;
    34     }
    35 }
    36 //中间的部分根据标记或者hash表可以直接查询,两边的sqrt(n)暴力查询
    37 int query(int l,int r,int c){
    38     int lb=l/bsize,rb=r/bsize,ans=0;
    39     for(int i=lb+1;i<rb;i++){
    40         //一直错在这个地方了,如果有标记,直接判断标记是不是需要的颜色
    41         //如果没标记,要先判map中有没有这个元素然后在操作,否则会MLE!
    42         if(b[i].cls==c)ans+=b[i].size;
    43         else if(b[i].cls==-1&&b[i].mp.find(c)!=b[i].mp.end())ans+=b[i].mp[c];
    44     }
    45     if(lb!=rb){
    46         pushdown(lb);pushdown(rb);
    47         for(int i=l;i<lb*bsize+b[lb].size;i++)ans+=(x[i]==c);
    48         for(int i=rb*bsize;i<=r;i++)ans+=(x[i]==c);
    49     }else{
    50         pushdown(lb);
    51         for(int i=l;i<=r;i++)ans+=(x[i]==c);
    52     }
    53     return ans;
    54 }
    55 void initblock(){
    56     bsize=(int)sqrt(n+1e-8);
    57     bnum=(n-1)/bsize+1;
    58     for(int i=0;i<bnum;i++){
    59         b[i].mp.clear();
    60         b[i].cls=-1;
    61         b[i].size=std::min(i*bsize+bsize,n)-i*bsize;
    62     }
    63     for(int i=0;i<n;i++){
    64         scanf("%d",&x[i]);
    65         b[i/bsize].mp[x[i]]++;
    66     }
    67 }
    68 int q,l,r,z;
    69 int main(){
    70     //freopen("test.in","r",stdin);
    71     while(scanf("%d%d",&n,&m)!=EOF){
    72         initblock();
    73         while(m--){
    74             scanf("%d%d%d%d",&q,&l,&r,&z);
    75             if(q==1)update(l,r,z);
    76             else printf("%d\n",query(l,r,z));
    77         }
    78     }
    79     return 0;
    80 }
  • 相关阅读:
    再谈TextField
    IOS-TextField知多少
    leftBarButtonItems
    LeftBarButtonItems,定制导航栏返回按钮
    Apple Mach-O Linker (id) Error "_OBJC_CLASS...错误解决办法 Apple Mach-O Linker (id) Error "_OBJC_CLASS...错误解决办法
    Unrecognized Selector Sent to Instance问题之诱敌深入关门打狗解决办法
    UNRECOGNIZED SELECTOR SENT TO INSTANCE 问题快速定位的方法
    Present ViewController,模态详解
    UILABEL AUTOLAYOUT自动换行 版本区别
    iOS自动布局解决警告Automatic Preferred Max Layout Width is not available on iOS versions prior to 8.0
  • 原文地址:https://www.cnblogs.com/swm8023/p/2698780.html
Copyright © 2011-2022 走看看