• HDU 4391 Paint The Wall


    操作:
    1. 将 a b 区间染上颜色z
    2. 统计a b区间内颜色为z的点的个数
     
    此题若用普通线段树会退化成O(n)
     
    比赛时YY了一个map<int,int>的线段树 HLL的MLE了
     
    赛后才知道可以YY剪枝过 
     
    方法:记录区间被染的最小颜色和最大颜色 若查询颜色不在范围内则return (数据水了)
    更好的方法是标程上讲的分段Hash http://page.renren.com/601081183/note/867254911
     
     
     
    剪枝版代码:

    #include <iostream>
    #include <stdio.h>
    #include <string.h>
    #include <algorithm>
    #include <map>
    using namespace std;
    #define for if(0); else for


    const int N=65537*2;
    struct SegTree{
        int a[N<<1],mi[N<<1],mx[N<<1];
        int Q;

        void init(int n,int c[]){
            for(Q=1;Q<=n+2;Q<<=1);
            memset(a,0,sizeof(a));
            for(int i=Q+0;i<Q+n;i++) a[i]=mi[i]=mx[i]=c[i-Q];
            for(int i=Q-1;i>=1;i--) pushup(i);
        }
        void pushup(int rt) {
            a[rt]=a[rt<<1]==a[rt<<1|1]?a[rt<<1]:-1;
            mi[rt]=min(mi[rt<<1],mi[rt<<1|1]);
            mx[rt]=max(mx[rt<<1],mx[rt<<1|1]);
        }

        void update_one(int rt,int x) {
            a[rt]=mi[rt]=mx[rt]=x;
        }
        void pushdown(int rt) {
            if(a[rt]!=-1) {
                update_one(rt<<1,a[rt]);
                update_one(rt<<1|1,a[rt]);
            }
        }
        void update(int L,int R,int l,int r,int rt,int c) {
            if(a[rt]==c) return;
            if(L<=l && r<=R) {
                update_one(rt,c);
                return;
            }
            pushdown(rt);
            if(rt>=Q) return;
            int m=(l+r)>>1;
            if(L<=m) update(L,R,l,m,rt<<1,c);
            if(m<R) update(L,R,m+1,r,rt<<1|1,c);
            pushup(rt);
        }
        int query(int L,int R,int l,int r,int rt,int c) {
            int ret=0;
            if(L<=l && r<=R) {
                if(c>=mi[rt]&&c<=mx[rt]){
                    int m=(l+r)>>1;
                    if(a[rt]!=-1) return (a[rt]==c)?r-l+1:0;
                    else return query(L,R,l,m,rt<<1,c)+query(L,R,m+1,r,rt<<1|1,c);
                }else return 0;
            }
            if(rt>=Q) return ret;
            pushdown(rt);
            int m=(l+r)>>1;
            if(L<=m) ret+=query(L,R,l,m,rt<<1,c);
            if(m<R) ret+=query(L,R,m+1,r,rt<<1|1,c);
            return ret;
        }

    }st;

    int a[N];
    int n,m;

    int main() {
        while(scanf("%d%d",&n,&m)!=EOF) {
            for(int i=0;i<n;i++) scanf("%d",&a[i]);
            st.init(n,a);
            for(int i=0;i<m;i++) {
                int cmd,l,r,c;
                scanf("%d%d%d%d",&cmd,&l,&r,&c);
                if(cmd==1){
                    st.update(l,r,0,st.Q-1,1,c);
                }else {
                    printf("%d\n",st.query(l,r,0,st.Q-1,1,c));
                }
            }
        }
        return 0;
    }
     
     
    分段Hash版(用map<int,int>实现)代码:

    #include <iostream>
    #include <stdio.h>
    #include <string.h>
    #include <algorithm>
    #include <math.h>
    #include <map>
    using namespace std;

    const int N=100010;
    const int SQRTN=510;

    int n,m;

    int a[N];
    map<int,int> hash[SQRTN];
    int flag[SQRTN];
    int block_size;
    int block_num;



    void rehash(int block_no) {
        int st=block_no*block_size;
        int ed=st+block_size-1;
        if(ed>=n) ed=n-1;
        hash[block_no].clear();
        for(int i=st;i<=ed;i++) {
            hash[block_no][a[i]]++;
        }
        flag[block_no]=-1;
    }


    void rebuild(int block_no) {
        if(flag[block_no]!=-1) {
            int st=block_no*block_size;
            int ed=st+block_size-1;
            if(ed>=n) ed=n-1;
            for(int i=st;i<=ed;i++) a[i]=flag[block_no];
            flag[block_no]=-1;
        }
    }


    void build_hash() {
        block_size = int(sqrt(n*1.0)+1.00001);
        block_num = n/block_size + ( n%block_size !=0 ) ;
        for(int i=0;i<block_num;i++) {
            rehash(i);
        }
    }

    void update_block(int block_no,int sta,int end,int z) {
        if(z==flag[block_no]) return;
        rebuild(block_no);
        int st=block_no*block_size+sta;
        int ed=block_no*block_size+end;
        if(ed>=n) ed=n-1;
        for(int i=st;i<=ed;i++) {
            a[i]=z;
        }
        rehash(block_no);
    }

    int get_block(int block_no,int sta,int end,int z) {
        if(flag[block_no]!=-1) {
            return z==flag[block_no]?end-sta+1:0;
        }
        int st=block_no*block_size+sta;
        int ed=block_no*block_size+end;
        if(ed>=n) ed=n-1;

        int ret=0;
        for(int i=st;i<=ed;i++) {
            if(a[i]==z) ret++;
        }
        return ret;
    }
    void update(int l,int r,int z) {
        int lx=l/block_size;
        int ly=l%block_size;
        int rx=r/block_size;
        int ry=r%block_size;
        if(lx==rx){
            update_block(lx,ly,ry,z);
        }else{
            update_block(lx,ly,block_size-1,z);
            update_block(rx,0,ry,z);
        }
        for(int i=lx+1;i<=rx-1;i++) {
            flag[i]=z;
        }
    }

    int query(int l,int r,int z) {
        int lx=l/block_size;
        int ly=l%block_size;
        int rx=r/block_size;
        int ry=r%block_size;
        int ret=0;

        if(lx==rx){
            ret+=get_block(lx,ly,ry,z);
        }else{
            ret+=get_block(lx,ly,block_size-1,z);
            ret+=get_block(rx,0,ry,z);
        }
        for(int i=lx+1;i<=rx-1;i++) {
            if(flag[i]!=-1){
                if(z==flag[i]) ret+=block_size;
            }else {
                if(hash[i].find(z)!=hash[i].end()) ret+=hash[i][z];
            }
        }
        return ret;
    }

    int main() {
        while(scanf("%d%d",&n,&m)!=EOF) {
            for(int i=0;i<n;i++) scanf("%d",&a[i]);
            build_hash();
            for(int i=0;i<m;i++) {
                int cmd,l,r,z;
                scanf("%d%d%d%d",&cmd,&l,&r,&z);
                if(cmd==1) {
                    update(l,r,z);
                }else if(cmd==2){
                    printf("%d\n",query(l,r,z));
                }
            }
        }
        return 0;
    }
     
     
     
     
     
  • 相关阅读:
    基于WS流的RTSP监控,H5低延时,Web无插件,手机,微信ONVIF操控摄像头方案
    H5微信视频,直播低延时,IOS限制全屏播放,自动播放问题处理。
    最新IOS,safari11中对webrtc支持,IOS和android视频聊天,web低延时视频教学技术分析
    MySql 用户篇
    Sql Server 数据库帮助类
    [C#基础知识]转载 private、protected、public和internal的区别
    Mysql 插入语句
    .net core identityserver4 学习日志
    mysql 事务模板
    .net core 生成二维码
  • 原文地址:https://www.cnblogs.com/programCaiCai/p/HDU4391.html
Copyright © 2020-2023  润新知