UVA 12003 Array Transformer

Array Transformer

Time Limit: 5000ms

Memory Limit: 131072KB

This problem will be judged on UVA. Original ID: 12003
64-bit integer IO format: %lld      Java class name: Main

Write a program to transform an array A[1], A[2],..., A[n] according to m instructions. Each instruction (LRvp) means: First, calculate how many numbers from A[L] to A[R](inclusive) are strictly less than v, call this answer k. Then, change the value of A[p] to u*k/(R - L + 1), here we use integer division (i.e. ignoring fractional part).

Input

The first line of input contains three integer nmu ( 1n300, 000, 1m50, 000, 1u1, 000, 000, 000). Each of the next n lines contains an integer A[i] ( 1A[i]u). Each of the next m lines contains an instruction consisting of four integers LRvp ( 1LRn, 1vu, 1pn).

Output

Print n lines, one for each integer, the final array.

Sample Input

10 1 11
1
2
3
4
5
6
7
8
9
10
2 8 6 10

Sample Output

1
2
3
4
5
6
7
8
9
6

Explanation: 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.

解题:分块

参考lrj同学的那本大白

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 typedef long long LL;
 4 const int maxn = 300000 + 10;
 5 const int SIZE = 4096;
 6 int n,m,u,A[maxn],block[maxn/SIZE+1][SIZE];
 7 void init() {
 8     scanf("%d%d%d",&n,&m,&u);
 9     int b = 0,j = 0;
10     for(int i = 0; i < n; ++i) {
11         scanf("%d",A+i);
12         block[b][j] = A[i];
13         if(++j == SIZE) {
14             b++;
15             j = 0;
16         }
17     }
18     for(int i = 0; i < b; ++i)
19         sort(block[i],block[i] + SIZE);
20     if(j) sort(block[b],block[b]+j);
21 }
22 int query(int L,int R,int v) {
23     int lb = L/SIZE,rb = R/SIZE,k = 0;
24     if(lb == rb) {
25         for(int i = L; i <= R; ++i)
26             k += (A[i] < v);
27     } else {
28         for(int i = L; i < (lb+1)*SIZE; ++i)
29             if(A[i] < v) ++k;
30         for(int i = rb*SIZE; i <= R; ++i)
31             if(A[i] < v) ++k;
32         for(int i = lb+1; i < rb; ++i)
33             k += lower_bound(block[i],block[i]+SIZE,v) - block[i];
34     }
35     return k;
36 }
37 void update(int p,int x) {
38     if(A[p] == x) return;
39     int old = A[p],pos = 0,*B = &block[p/SIZE][0];
40     A[p] = x;
41     while(B[pos] < old) ++pos;
42     B[pos] = x;
43     while(pos < SIZE-1 && B[pos] > B[pos + 1]) {
44         swap(B[pos],B[pos+1]);
45         ++pos;
46     }
47     while(pos > 0 && B[pos] < B[pos - 1]) {
48         swap(B[pos],B[pos-1]);
49         --pos;
50     }
51 }
52 int main() {
53     init();
54     while(m--) {
55         int L,R,v,p;
56         scanf("%d%d%d%d",&L,&R,&v,&p);
57         --L;
58         --R;
59         --p;
60         int k = query(L,R,v);
61         update(p,(LL)u*k/(R - L + 1));
62     }
63     for(int i = 0; i < n; ++i)
64         printf("%d\n",A[i]);
65     return 0;
66 }

时间: 2024-11-04 15:36:48

UVA 12003 Array Transformer的相关文章

uva 12003 Array Transformer (块状数组)

大白书上的393页. 一直在原数组上乱搞.其实要用另外一个数组记录块. 原数组是不能变的. 注意好原数组和块数组的关系,细心一点处理边界.还是不难的. #include <cstdio> #include <iostream> #include <algorithm> #include <cstring> #define maxn 300005 #define SIZE 600 using namespace std; int a[maxn]; int bl

uva 11922 - Permutation Transformer(伸展树)

题目链接:uva 11922 - Permutation Transformer 题目大意:给定一个序列,每次操作取出区间a~b,翻转后放到末尾,随后输出序列. 解题思路:就是伸展树,对于每个节点设一个flip,表示是否为翻转转态.每次将a旋转到根,然后分裂,再将b翻转到根,分裂,然后将mid翻转放到最后. #include <cstdio> #include <cstring> #include <algorithm> using namespace std; str

UVA - 348Optimal Array Multiplication Sequence(递推)

题目:Optimal Array Multiplication Sequence 题目大意:给出N个矩阵相乘,求这些矩阵相乘乘法次数最少的顺序. 解题思路:矩阵相乘不满足交换率但满足结合率.dp[i][j] 代表第1个矩阵到第j个矩阵之间的最少的乘法次数,转移状态方程:dp[i][j] = Min(dp[i][k] + dp[k + 1][j]  + A[i - 1] * A[k] *A[j]) k>= i && k <= j - 1.A0A1A2A3..Ak  |  Ak+1

Array Transformer UVA - 12003

题目:传送门 题意: 给你n个数,要进行m次操作 对于每次操作(l,r,v,p)代表:在区间[l,r]中有x(这个x是需要你自己找出来的)个数小于v,你需要把序列的第p个位置的值改成u∗k/(r−l + 1) 最后输出序列就完了 题解: 因为他要找出来区间中有多少数小于v,所以我们就要维护一个数组a,在这个a数组里面要放置每一块排序后的结束(我的代码是从小到大排序).为什么要排序,因为对于一个序列排完序之后我们可以通过二分找出来小于v的那个数的位置,然后我们又知道每一个块的左区间位置和右区间位置

uva 12003 块状链表

先分块.对于查询,块内排好序二分,对于修改,直接暴力,注意需要维护原来的有序性,不断和块内相邻元素交换即可. 1 #include <algorithm> 2 #include <iostream> 3 #include <cstring> 4 #include <cstdio> 5 #include <cmath> 6 using namespace std; 7 8 const int N = 300000; 9 const int M =

[UVA12003] Array Transformer(分块,二分,暴力)

题目链接:https://vjudge.net/problem/UVA-12003 题意:n个数,每次查询[l,r]区间内比v小的数的个数,并且要更新一个位置为另一个值,强制在线. 首先分块,分块后对每一个块排序,查询遇到块的时候二分找比这个值小的,两端则枚举. 更新的时候,修改一个值,冒泡就行了. 1 #include <bits/stdc++.h> 2 using namespace std; 3 4 typedef long long LL; 5 const int maxn = 300

UVA 11922 Permutation Transformer —— splay伸展树

题意:根据m条指令改变排列1 2 3 4 - n ,每条指令(a, b)表示取出第a~b个元素,反转后添加到排列尾部 分析:用一个可分裂合并的序列来表示整个序列,截取一段可以用两次分裂一次合并实现,粘贴到末尾可以用一次合并实现. 翻转可以采用在每个结点上做标记的方法,flip = 1意味着将这棵子树翻转,可以类似线段树用一个pushdown()实现标记向下传递. 可以发现当前排列就是伸展树的中序遍历序列.中序遍历打印结果即可. 注意代码中设置了虚拟首结点0的技巧. 代码如下: 1 #includ

Uva 11922 Permutation Transformer

闲的没事打了打一个splay,,,,, 注意只要是遍历数据结构就要下传标记!!!! 只要是修改就要维护所有受到影响的!!! 希望以后不要再犯这种zz错误了hhh #include<iostream> #include<cstdio> #include<algorithm> #include<cmath> #include<cstring> #include<cstdlib> #define ll long long #define m

11922 - Permutation Transformer (Splay区间翻转)

UVA 11922 - Permutation Transformer 题目链接 题意:给一个序列,每次操作选择(a,b),把(a,b)序列翻转之后加到末尾,求最终序列 思路:Splay的应用,多一个flip标记,在开头多一个虚拟的0结点,这样每次就利用Splay进行分裂合并即可 代码: #include <cstdio> #include <cstring> #include <cstdlib> #include <algorithm> #include