刷漆升级

来源:互联网 发布:mariadb与mysql性能 编辑:程序博客网 时间:2024/04/26 01:10

虽然说这题暴力有95,
但正解的想法还是很值得学习的
对于一个时刻更新的区间,且这个区间有许多要更新的值
使用线段树的话,在更新子树时复杂度会很高
这里采用map+分块的方法 复杂度约为O(nloglogn)

#include<cstdio>#include<cmath>#include<map>using namespace std;#define M 100005#define N 330#define yzk is not  yz_gay //分块+map离散 struct node{    int col;    map<int,int>mp;    node(){col=-1;}}B[N];int A[M],m;void change(int k){    if(B[k].col==-1)return;    for(int i=k*m;i<k*m+m;i++)A[i]=B[k].col;    B[k].col=-1;}void update(int l,int r,int col){    int L=l/m,R=r/m;    if(L==R){        change(L);        for(int i=l;i<=r;i++){            B[L].mp[A[i]]--;            A[i]=col;            B[L].mp[A[i]]++;        }        return;    }    change(L);    for(int i=l;i<L*m+m;i++){        B[L].mp[A[i]]--;        A[i]=col;        B[L].mp[A[i]]++;        }    for(int i=L+1;i<R;i++){        B[i].col=col;        B[i].mp.clear();        B[i].mp[col]=m;    }    change(R);    for(int i=R*m;i<=r;i++){        B[R].mp[A[i]]--;        A[i]=col;        B[R].mp[A[i]]++;        }}int query(int l,int r,int col){    int L=l/m,R=r/m,cnt=0;    if(L==R){        change(L);        for(int i=l;i<=r;i++)if(A[i]==col)cnt++;        return cnt;    }    change(L);    for(int i=l;i<L*m+m;i++)if(A[i]==col)cnt++;    for(int i=L+1;i<R;i++)cnt+=B[i].mp[col];    change(R);    for(int i=R*m;i<=r;i++)if(A[i]==col)cnt++;    return cnt;}int main(){    int n,q;    scanf("%d%d",&n,&q);    for(int i=0;i<n;i++)scanf("%d",&A[i]);    m=sqrt(n);    for(int i=0;i<n;i++)B[i/m].mp[A[i]]++;      while(q--){        int l,r,op,col;        scanf("%d %d %d %d",&op,&l,&r,&col);        if(op==1)update(l,r,col);        else printf("%d\n",query(l,r,col));    }    return 0;}
原创粉丝点击