uva12003 - Array Transformer 分块结构

原创 2015年07月09日 16:33:48

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>
#pragma comment(linker, "/STACK:102400000,102400000")
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;
}


uva12003 Array Transformer 分块

题目:https://vjudge.net/problem/UVA-12003题意:给出一个长度为nn的序列aa,有mm次操作,每次操作(L,R,v,p)(L,R,v,p),首先找出[L,R][L,R...
  • discreeter
  • discreeter
  • 2017年10月09日 15:48
  • 110

UVA - 12003 Array Transformer(分块)

题意:给一列数,每次询问  将 a[ pi ]  的值 更新为  li  到  ri  区间中小于  vi 的个数 *  u / (r-l+1); 解:将数列分块 快内排序 每次查询  若不是整块直...
  • yjf3151731373
  • yjf3151731373
  • 2017年10月07日 00:48
  • 53

UVA 12003 Array Transformer (分块)

题意: 给你n 个数,和m 个操作,m 个操作先查询 [L,R]上比x 小的个数, 在根据这个数 对 某个数进行变换。 思路: 真的是xjb 操作啊,直接分块怼就行。 直接建立一个有序的分块即...
  • aozil_yang
  • aozil_yang
  • 2017年03月29日 20:33
  • 404

UVA 12003 Array Transformer (分块)

题意: 给出数组A[1,2,...,n]和m条指令,每条指令形如(L,R,v,p)表示统计出A[L]...A[R]中严格小于v的有多少个,然后把A[p]修改成uk/(R−L+1)给出数组A[1,2...
  • lwt36
  • lwt36
  • 2015年11月12日 17:53
  • 260

【uva 12003 Array Transformer】【分块】

题意:给定一个序列,要求查询一个区间内有多少个数小于v。并且把第p个位置的值改为u * k / (R - L + 1)。思路:单点修改和区间查询。 线段树的话还要套平衡树,不会写,也不想写(:зゝ∠...
  • guhaiteng
  • guhaiteng
  • 2017年03月22日 23:53
  • 144

UVA 12003 Array Transformer [分块]

Array Transformer Time Limit: 5000MS 64bit IO Format: %lld & %lluDescription Write a prog...
  • ourfutr2330
  • ourfutr2330
  • 2016年08月08日 12:46
  • 257

【分块】UVA 12003 Array Transformer 水题

点击打开链接 比较水的分快,还不会爆LL #include #include #include #include #include #include #include using...
  • u012749539
  • u012749539
  • 2015年08月04日 09:36
  • 351

uva 12003 - Array Transformer(分块+树套树)

题意:给出数组A[1,2,...,n]和m条指令,每条指令形如(L,R,v,p)表示统计出A[L]...A[R]中严格小于v的有多少个,然后把A[p]修改成uk/(R-L+1) 思路:首先是分块,将数...
  • u010660276
  • u010660276
  • 2015年05月19日 14:47
  • 435

UVA12003.Array Transformer——分块

http://www.bnuoj.com/v3/problem_show.php?pid=20421题目分析: 输入一个数组A[1,…,n]和m条指令,你的任务是对数组进行变换,输出最终结果。每条指...
  • u014141559
  • u014141559
  • 2015年05月10日 22:06
  • 397

深度学习方法(十二):卷积神经网络结构变化——Spatial Transformer Networks

今天具体介绍一个Google DeepMind在15年提出的Spatial Transformer Networks,相当于在传统的一层Convolution中间,装了一个“插件”,可以使得传统的卷积...
  • xbinworld
  • xbinworld
  • 2017年04月03日 23:45
  • 5752
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:uva12003 - Array Transformer 分块结构
举报原因:
原因补充:

(最多只允许输入30个字)