线段树(区间更新)codeforces 292E Copying Data

来源:互联网 发布:南京浦口行知中学 编辑:程序博客网 时间:2024/06/05 11:57

对应 codeforces 题目:点击打开链接

E. Copying Data
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

We often have to copy large volumes of information. Such operation can take up many computer resources. Therefore, in this problem you are advised to come up with a way to copy some part of a number array into another one, quickly.

More formally, you've got two arrays of integers a1, a2, ..., an and b1, b2, ..., bn of length n. Also, you've got m queries of two types:

  1. Copy the subsegment of array a of length k, starting from position x, into array b, starting from position y, that is, executeby + q = ax + q for all integer q (0 ≤ q < k). The given operation is correct — both subsegments do not touch unexistent elements.
  2. Determine the value in position x of array b, that is, find value bx.

For each query of the second type print the result — the value of the corresponding element of array b.

Input

The first line contains two space-separated integers n and m (1 ≤ n, m ≤ 105) — the number of elements in the arrays and the number of queries, correspondingly. The second line contains an array of integers a1, a2, ..., an (|ai| ≤ 109). The third line contains an array of integers b1, b2, ..., bn (|bi| ≤ 109).

Next m lines contain the descriptions of the queries. The i-th line first contains integer ti — the type of the i-th query (1 ≤ ti ≤ 2). Ifti = 1, then the i-th query means the copying operation. If ti = 2, then the i-th query means taking the value in array b. If ti = 1, then the query type is followed by three integers xi, yi, ki (1 ≤ xi, yi, ki ≤ n) — the parameters of the copying query. If ti = 2, then the query type is followed by integer xi (1 ≤ xi ≤ n) — the position in array b.

All numbers in the lines are separated with single spaces. It is guaranteed that all the queries are correct, that is, the copying borders fit into the borders of arrays a and b.

Output

For each second type query print the result on a single line.

Examples
input
5 101 2 0 -1 33 1 5 -2 02 51 3 3 32 52 42 11 2 1 42 12 41 4 2 12 2
output
03-1323-1

题意:

        给两个数组 a[] 和 b[],有两个操作,(1, x, y, k) 表示把数组 a[] 从下标 x 的那个数开始的 k 个数覆盖数组 b[] 的从下标 y 开始的 k 个数(即用 a[x]~a[x+k-1] 覆盖 b[y]~b[y+k-1]),(2, x) 表示请求输出数组 b[x] 的值。题目保证给出的数据合理。


思路:

        线段树区间更新,线段树的每个结点维护数组 a[] 覆盖数组 b[] 的左右边界


试着用 Go 写了下,超时了~ 出乎意料,完全一样的方法。。。

Go :2000ms+

C   :280ms

有点失望。。。


Go:

package mainimport "fmt"const N = 100010var a [N]inttype tree struct{val, al, ar intmid, l, r int}var T [N]treefunc down(rt int){tal := T[rt].altar := T[rt].arlson_len := T[rt].mid - T[rt].l + 1if tal != tar {T[rt<<1].al = talT[rt<<1].ar = tal + lson_len - 1T[rt<<1|1].al = tal + lson_lenT[rt<<1|1].ar = tarT[rt].al = -1T[rt].ar = -1}}func build_tree(rt, l, r, pos int){T[rt].al = -1T[rt].ar = -1T[rt].mid = (l + r) / 2T[rt].l = lT[rt].r = rif l == r{fmt.Scan(&T[rt].val)return}m := T[rt].midif pos <= m {build_tree(rt<<1, l, m, pos)}else{build_tree(rt<<1|1, m+1, r, pos)}}func update(rt, l1, r1, l2, r2 int){l := T[rt].lr := T[rt].rif l2 == l && r2 == r{T[rt].al = l1T[rt].ar = r1return}down(rt)m := T[rt].midif r2 <= m{update(rt<<1, l1, r1, l2, r2)}else if l2 > m{update(rt<<1|1, l1, r1, l2, r2)}else{update(rt<<1, l1, l1+(m-l2), l2, m)update(rt<<1|1, l1+(m-l2)+1, r1, m+1, r2)}}func query(rt, pos int) int{l := T[rt].lr := T[rt].rif l == r{if T[rt].al != -1{return a[T[rt].al]}else{return T[rt].val}}down(rt)m := T[rt].midif pos <= m{return query(rt<<1, pos)}else{return query(rt<<1|1, pos)}}func main(){var n, q intvar od intvar ax, bx, k intvar x intfor{num, _ := fmt.Scanln(&n, &q)if num != 2{break}var i intfor i = 0; i < n; i++{fmt.Scan(&a[i])}for i = 0; i < n; i++{build_tree(1, 0, n-1, i)}for i = 0; i < q; i++{fmt.Scan(&od)if od == 1{fmt.Scan(&ax, &bx, &k)ax--bx--update(1, ax, ax+k-1, bx, bx+k-1)}else if od == 2{fmt.Scan(&x)x--v := query(1, x)fmt.Println(v)}}}}

C:

#include <stdio.h>#include <stdlib.h>#include <string.h>#define N 100010int a[N];int b[N<<2];int al[N<<2];int ar[N<<2];void down(int rt, int lson_len){if(al[rt] != ar[rt]){al[rt<<1] = al[rt];ar[rt<<1] = al[rt] + lson_len - 1;al[rt<<1|1] = al[rt] + lson_len;ar[rt<<1|1] = ar[rt];al[rt] = ar[rt] = -1;}}void build_tree(int rt, int l, int r, int pos){int mid;al[rt] = ar[rt] = -1;if(l == r){scanf("%d", b + rt);return;}mid = (l + r) / 2;if(pos <= mid)build_tree(rt<<1, l, mid, pos);else build_tree(rt<<1|1, mid + 1, r, pos);}void update(int rt, int l, int r, int l1, int r1, int l2, int r2){int mid;if(l2 == l && r2 == r){al[rt] = l1;ar[rt] = r1;return;}mid = (l + r) / 2;down(rt, mid-l+1);if(r2 <= mid)update(rt<<1, l, mid, l1, r1, l2, r2);else if(l2 > mid)update(rt<<1|1, mid + 1, r, l1, r1, l2, r2);else{update(rt<<1, l, mid, l1, l1+(mid-l2), l2, mid);update(rt<<1|1, mid+1, r, l1+(mid-l2)+1, r1, mid+1, r2);}}int query(int rt, int l, int r, int pos){int mid;if(l == r){if(al[rt] != -1)return a[al[rt]];else return b[rt];}mid = (l + r) / 2;down(rt, mid-l+1);if(pos <= mid)return query(rt<<1, l, mid, pos);elsereturn query(rt<<1|1, mid + 1, r, pos);}int main(){#if 0freopen("in.txt","r",stdin);#endifint n, q;while(~scanf("%d%d", &n ,&q)){int i;for(i = 0; i < n; i++)scanf("%d", a + i);for(i = 0; i < n; i++){build_tree(1, 0, n-1, i);}while(q--){int od;scanf("%d", &od);if(od == 1){int ax, bx, k;scanf("%d%d%d", &ax, &bx, &k);ax--; bx--;update(1, 0, n-1, ax, ax+k-1, bx, bx+k-1);}else if(od == 2){int x;scanf("%d", &x);x--;printf("%d\n", query(1, 0, n-1, x));}}}return 0;}





0 0
原创粉丝点击