uva12003 - Array Transformer 分块结构

334人阅读 评论(0)

Write a program to transform an array A[1], A[2], . . . , A[n] according to m instructions. Each instruction(L, R, v, p) means: First, calculate how many numbers from A[L] to A[R] (inclusive) are strictly lessthan v, call this answer k. Then, change the value of A[p] to u ∗ k/(R − L + 1), here we use integerdivision (i.e. ignoring fractional part).InputThe first line of input contains three integer n, m, u (1 ≤ n ≤ 300, 000, 1 ≤ m ≤ 50, 000, 1 ≤ u ≤1, 000, 000, 000). Each of the next n lines contains an integer A[i] (1 ≤ A[i] ≤ u). Each of the nextm lines contains an instruction consisting of four integers L, R, v, p (1 ≤ L ≤ R ≤ n, 1 ≤ v ≤ u,1 ≤ p ≤ n).OutputPrint n lines, one for each integer, the final array.Sample Input10 1 11123456789102 8 6 10Sample Output1234567896Explanation: There is only one instruction: L = 2, R = 8, v = 6, p = 10. There are 4 numbers(2,3,4,5) less than 6, so k = 4. The new number in A[10] is 11 ∗ 4/(8 − 2 + 1) = 44/7 = 6.

输入N（1<=N<=300000),M(1<=M<=50000),U(1<=U<=10^9)，接下来输入数组a（N个数），M次操作，每次操作输入L,R,V,P，计算出[L,R]区间内小于V的数的个数k，把A[P]修改为U*k/(R-L+1)。最后输出M次操作后的数组。

把数组分块，每块大小在根号N附近（这样比较快），对每块排序，这样每次询问L,R的时候在L,R所在的块进行暴力查找，L,R之间的块用二分查找。修改的时候不光要修改原数组，还要修改分块数组，找到P所在的块，然后找到要修改的值所在的位置，把这个位置替换为新值，再维护块内的顺序。找L，R所在块的位置很好找，因为是按顺序分的，所以直接用位置除以块大小就是块编号。

分块法其实也就是划分成小范围的暴力，这里如果块大小取根号N的话，复杂度O(M*√N*log√N)， 白书上说分块法非常有用，很多用伸展树或树套树能解决的问题用分块法。

#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<vector>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<algorithm>
using namespace std;
typedef long long LL;

const int MAXN=300010;
const int SIZE=4096;
const int INF=0x3f3f3f3f;

int N,M,U,L,R,V,P;
int a[MAXN],block[MAXN/SIZE+1][SIZE];

int query(int l,int r,int v){
int lb=l/SIZE,rb=r/SIZE;
int ret=0;
if(lb==rb){
for(int i=l;i<=r;i++) if(a[i]<v) ret++;
}
else{
for(int i=l;i<(lb+1)*SIZE;i++) if(a[i]<v) ret++;
for(int i=rb*SIZE;i<=r;i++) if(a[i]<v) ret++;
for(int i=lb+1;i<rb;i++) ret+=lower_bound(block[i],block[i]+SIZE,v)-block[i];
}
return ret;
}

void change(int p,int x){
if(a[p]==x) return;
int old=a[p],pos=0,*b=block[p/SIZE];
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+1],b[pos]);
pos++;
}
}
else{
while(pos>0&&b[pos]<b[pos-1]){
swap(b[pos-1],b[pos]);
pos--;
}
}
}

int main(){
freopen("in.txt","r",stdin);
while(scanf("%d%d%d",&N,&M,&U)!=EOF){
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);
while(M--){
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]);
}
return 0;
}


0
0

【直播】机器学习&数据挖掘7周实训--韦玮
【套餐】系统集成项目管理工程师顺利通关--徐朋
【直播】3小时掌握Docker最佳实战-徐西宁
【套餐】机器学习系列套餐（算法+实战）--唐宇迪
【直播】计算机视觉原理及实战--屈教授
【套餐】微信订阅号+服务号Java版 v2.0--翟东平
【直播】机器学习之矩阵--黄博士
【套餐】微信订阅号+服务号Java版 v2.0--翟东平
【直播】机器学习之凸优化--马博士
【套餐】Javascript 设计模式实战--曾亮

* 以上用户言论只代表其个人观点，不代表CSDN网站的观点或立场
个人资料
• 访问：102913次
• 积分：3580
• 等级：
• 排名：第9115名
• 原创：267篇
• 转载：6篇
• 译文：0篇
• 评论：1条
文章分类
最新评论