UVA

来源:互联网 发布:windows mobile 编辑:程序博客网 时间:2024/06/03 22:41

题意:给一列数,每次询问  将 a[ pi ]  的值 更新为  li  到  ri  区间中小于  vi 的个数 *  u / (r-l+1);

解:将数列分块 快内排序 每次查询  若不是整块直接循环 若是整块 在快内二分查询 更新时在块内找到原来的值更新 再将块排序 其中有些优化操作

#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#include <bits/stdc++.h>using namespace std;const int N = 300000+10;typedef long long LL;LL p[N][700], a[N];LL id[N], lx[N], rx[N];LL solve(LL l,LL r,LL v){    if(id[l]==id[r])    {        LL num=0;        for(LL i=l; i<=r; i++)   if(a[i]<v) num++;        return num;    }    else    {        LL num=0;        for(LL i=l; i<=rx[id[l]]; i++) if(a[i]<v) num++;        for(LL i=lx[id[r]]; i<=r; i++) if(a[i]<v) num++;        for(LL i=id[l]+1; i<id[r]; i++)        {            LL cnt=p[i][0];            num+=(lower_bound(p[i]+1,p[i]+cnt+1,v)-(p[i]+1));        }        return num;    }}void change(LL v,LL x){    if(a[v]==x) return ;    LL k=id[v], cnt=p[id[v]][0], y=a[v];    a[v]=x;    LL pos=1;    while(p[k][pos]<y) pos++;    p[k][pos]=x;    if(x>y)        while(pos<cnt&&p[k][pos]>p[k][pos+1])        {            swap(p[k][pos],p[k][pos+1]);            pos++;        }    else        while(pos>1&&p[k][pos]<p[k][pos-1])        {            swap(p[k][pos],p[k][pos-1]);            pos--;        }    return ;}int main(){    LL n, k;    LL  m, u, i, l, r;    while(scanf("%lld %lld %lld", &n, &m, &u)!=EOF)    {        k=(LL)(sqrt(1.0*n));        for(i=1; i<=n; i++) scanf("%lld", &a[i]);        for(i=1; i*k<n; i++)        {            lx[i]=(i-1)*k+1,rx[i]=i*k;            for(LL j=lx[i],h=1; j<=rx[i]; j++,h++) p[i][h]=a[j],id[j]=i;            p[i][0]=k;            sort(p[i]+1,p[i]+1+k);        }        lx[i]=(i-1)*k+1,rx[i]=n;        for(LL j=lx[i],h=1; j<=rx[i]; j++,h++) p[i][h]=a[j],id[j]=i;        p[i][0]=rx[i]-lx[i]+1;        sort(p[i]+1,p[i]+1+p[i][0]);        while(m--)        {            LL v, px;            scanf("%lld %lld %lld %lld",&l, &r, &v, &px);            LL num=solve(l,r,v);            change(px,(LL)num*u/(r-l+1));        }        for(int i=1; i<=n; i++) printf("%lld\n",a[i]);    }    return 0;}/*10 2 11123456789102 8 6 109 10 5 10*/


原创粉丝点击