UVA 12003 Array Transformer (分块)

来源:互联网 发布:淘宝缩水女是谁 编辑:程序博客网 时间:2024/06/05 02:07

题意:

给出数列长度为 N 的数列,做 M 次操作和一个常数 U。

每次操作为求出 L R 区间内小于 V 的数的个数 K ,并将数列第 P 个数修改为 U * K /  ( R - L + 1 )。

输出变化后最终的数列。

思路:

分块维护数据

预处理:对每个块排序 sqrt(n)*log(sqrt(n))

查询 K 复杂度为 sqrt(n)*log(sqrt(n))

修改复杂度为 sqrt(n)

总的复杂度大概为 O(m*sqrt(n)*log(sqrt(n)))3e8左右

代码:

#include <bits/stdc++.h>using namespace std;const int MAXN=3e5+7;int blen,belong[MAXN],r[MAXN],l[MAXN],num;int a[MAXN],b[MAXN],u;int n,m;void build(){    blen=sqrt(n);    num=n/blen;if(n%blen) num++;    for(int i=1;i<=num;i++) l[i]=blen*(i-1)+1,r[i]=blen*i;    r[num]=n;    for(int i=1;i<=num;i++){        for(int j=l[i];j<=r[i];j++)            belong[j]=i;        sort(a+l[i],a+r[i]+1);    }}int query(int st,int en,int v){    int ans=0;    if(belong[st]==belong[en]){        ans=lower_bound(a+st,a+en+1,v)-a-st;    }else{        for(int i=st;i<=r[belong[st]];i++) ans+=b[i]<v;        for(int i=belong[st]+1;i<belong[en];i++)            ans+=lower_bound(a+l[i],a+r[i]+1,v)-a-l[i];        for(int i=l[belong[en]];i<=en;i++) ans+=b[i]<v;    }    return ans;}void update(int st,int en,int k,int p){    int bel=belong[p];    int pos=lower_bound(a+l[bel],a+r[bel]+1,b[p])-a;    int now=(long long)u*k/(en-st+1);    a[pos]=now;    if(now<b[p]){        while(pos>l[bel]&&a[pos]<a[pos-1]) swap(a[pos],a[pos-1]),pos--;    }else{        while(pos<r[bel]&&a[pos]>a[pos+1]) swap(a[pos],a[pos+1]),pos++;    }    b[p]=now;}int main(){    int st,en,v,p;    while(scanf("%d%d%d",&n,&m,&u)!=-1){        for(int i=1;i<=n;i++) scanf("%d",&a[i]),b[i]=a[i];        build();        for(int i=1;i<=m;i++){            scanf("%d%d%d%d",&st,&en,&v,&p);            update(st,en,query(st,en,v),p);        }        for(int i=1;i<=n;i++) printf("%d\n",b[i]);    }}




原创粉丝点击