HDU 4391 Paint The Wall 分块HASH

本文详细解析了HDU4391 Paint The Wall的算法实现,采用分块HASH技术进行区间计数和区间推平操作,通过标记优化时间复杂度。介绍了使用map和vector维护数据结构的方法,以及如何通过二分查找提高效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

/**
HDU 4391 Paint The Wall 分块HASH
链接:http://acm.hdu.edu.cn/showproblem.php?pid=4391
区间计数+区间推平;
分块HASH+标记;
************tricks**********
map<>mp;时间复杂度  竟然被称为O(1);
vector维护升序  二分查log复杂度不可避免 感觉复杂度差不多呀;
估计是数据针对排序所需复杂度多了一个log;
*/
#include<bits/stdc++.h>
#define ll long long
using namespace std;

const int maxn=1e5+7;
int n,m,blo,x[maxn],pos[maxn];

struct node{
     int cls,sz;
     map<int,int>mp;
}b[500];

void pushdown(int id){
    if(b[id].cls!=-1){
        for(int i=(id-1)*blo+1;i<=min(n,id*blo);i++) x[i]=b[id].cls;
        b[id].mp.clear(),b[id].mp[b[id].cls]=b[id].sz;
        b[id].cls=-1;
    }
}

void update(int l,int r,int c){
    for(int i=pos[l]+1;i<=pos[r]-1;i++) b[i].cls=c;

    if(pos[l]!=pos[r]){
        pushdown(pos[l]);pushdown(pos[r]);
        for(int i=l;i<=pos[l]*blo;i++) b[pos[l]].mp[x[i]]--,b[pos[l]].mp[c]++,x[i]=c;
        for(int i=(pos[r]-1)*blo+1;i<=r;i++) b[pos[r]].mp[x[i]]--,b[pos[r]].mp[c]++,x[i]=c;
    }
    else{
        pushdown(pos[l]);
        for(int i=l;i<=r;i++) b[pos[l]].mp[x[i]]--,b[pos[l]].mp[c]++,x[i]=c;
    }
}

int query(int l,int r,int c){
    int ans=0;
    for(int i=pos[l]+1;i<=pos[r]-1;i++){
        if(b[i].cls==c) ans+=b[i].sz;
        else if(b[i].cls==-1&&b[i].mp.find(c)!=b[i].mp.end()) ans+=b[i].mp[c];
    }
    if(pos[l]!=pos[r]){
        pushdown(pos[l]);pushdown(pos[r]);
        for(int i=l;i<=pos[l]*blo;i++) ans+=(x[i]==c);
        for(int i=(pos[r]-1)*blo+1;i<=r;i++)ans+=(x[i]==c);
    }
    else{
        pushdown(pos[l]);
        for(int i=l;i<=r;i++)ans+=(x[i]==c);
    }
    return ans;
}

int q,l,r,z;

int main(){
    while(~scanf("%d %d",&n,&m)){
        blo=(int)sqrt(n*1.0);
        for(int i=1;i<=n;i++) pos[i]=(i-1)/blo+1;
        for(int i=1;i<=pos[n];i++){
            b[i].mp.clear();
            b[i].cls=-1;
            b[i].sz=min(i*blo,n)-(i-1)*blo;
        }
        for(int i=1;i<=n;i++) {
            scanf("%d",&x[i]);
            b[pos[i]].mp[x[i]]++;
        }
        while(m--){
            scanf("%d %d %d %d",&q,&l,&r,&z);l++,r++;
            if(q==1) update(l,r,z);
            else printf("%d\n",query(l,r,z));
        }
    }
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值