http://www.bnuoj.com/v3/problem_show.php?pid=20421
题目分析:
输入一个数组A[1,…,n]和m条指令,你的任务是对数组进行变换,输出最终结果。每条指令形如(L,R,v,p),表示先统计出A[L],A[L+1],…,A[R]中严格小于v 的元素个数k,然后把A[p]修改成uk/(R-L+1)。这里的除法为整数除法
分析:
可以用嵌套数据结构
这里用分块
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cmath>
typedef long long LL;
using namespace std;
const int MAXN = 300010;
const int SIZE = 4096;
int n,m,u,a[MAXN],block[MAXN/SIZE+1][SIZE];
void init(){
scanf("%d%d%d",&n,&m,&u);
int b=0,j=0;
for(int i=0;i<n;++i){
scanf("%d",&a[i]);
block[b][j++]=a[i];
if(j==SIZE){b++;j=0;}
}
for(int i=0;i<b;++i) sort(block[i],block[i]+SIZE);
if(j) sort(block[b],block[b]+j);//j==0没有block[b],否则有block[b]
}
int query(int L,int R,int v){
int lb=L/SIZE,rb=R/SIZE;
int k=0;
if(lb==rb){
for(int i=L;i<=R;++i){
if(a[i]<v) k++;
}
}else{
for(int i=L;i<(lb+1)*SIZE;++i){
if(a[i]<v) k++;
}
for(int i=rb*SIZE;i<=R;++i){
if(a[i]<v) k++;
}
for(int b=(lb+1);b<rb;++b){
k+=lower_bound(block[b],block[b]+SIZE,v)-block[b];
}
}
return k;
}
void change(int p,int x){
if(a[p]==x) return ;
int old=a[p],pos=0,*b=&block[p/SIZE][0];
a[p]=x;
while(b[pos]<old) pos++;b[pos]=x;
if(x>old)
while(pos<SIZE-1&&b[pos]>b[pos+1]){
swap(b[pos],b[pos+1]);
pos++;
}
else
while(pos>0&&b[pos]<b[pos-1]){
swap(b[pos],b[pos-1]);
pos--;
}
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.cpp","r",stdin);
#endif // ONLINE_JUDGE
init();
while(m--){
int L,R,v,p;
scanf("%d%d%d%d",&L,&R,&v,&p);
L--;R--;p--;
int k=query(L,R,v);
change(p,(LL)u*k/(R-L+1));
}
for(int i=0;i<n;++i) printf("%d\n",a[i]);
// cout<<"--------"<<endl;
return 0;
}