Croc Champ 2013 - Round 1——E. Copying Data

134 阅读1分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第5天,点击查看活动详情

Croc Champ 2013 - Round 1——E. Copying Data

Problem - E - Codeforces

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, ..., a n and b1, b2, ..., b n 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, execute b y + q = a x + 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 b**x.

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, ..., a n (|a i| ≤ 109). The third line contains an array of integers b1, b2, ..., b n (|b i| ≤ 109).

Next m lines contain the descriptions of the queries. The i-th line first contains integer t i — the type of the i-th query (1 ≤ t i ≤ 2). If t i = 1, then the i-th query means the copying operation. If t i = 2, then the i-th query means taking the value in array b. If t i = 1, then the query type is followed by three integers x i, y i, k i (1 ≤ x i, y i, k i ≤ n) — the parameters of the copying query. If t i = 2, then the query type is followed by integer x i (1 ≤ x i ≤ 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 10
1 2 0 -1 3
3 1 5 -2 0
2 5
1 3 3 3
2 5
2 4
2 1
1 2 1 4
2 1
2 4
1 4 2 1
2 2

output

0
3
-1
3
2
3
-1

问题解析

题目是说,给你两个数组a和b,有两种操作,第一种是把a数组的第x个数到第x+k-1个数赋值给b数组的第y个到第y+k-1个位置,第二种操作是询问b数组的第x个数是多少。

真的给b数组赋上对应的值肯定不现实,用啥数据结构也做不来。一开始想着,给b数组赋值上a数组的下标,每次询问如果下标为0说明这个位置还没被修改,输出b[x],如果被修改了,就输出对应的a数组的数。这样的话用区间赋值等差数列和单点查询就可以。(因为下标其实就是以x为首项,公差为1的等差数列,一共赋值k项)

但是咱不会区间赋值等差数列(也许根本做不到?),于是换了个方法。

我们给b数组的每个位置打上一个偏移量f,如果b数组的这个位置被修改过,相当于输出a[x+f[x]]。如果没被修改过,就输出b[x]。

而因为操作1的赋值,是给数组b的第y到第y+k-1个位置分别赋值上数组a的第x到第x+k-1的数,那么也就是说每个修改过后的数,相距之前的位置x-y个距离。

此时问题就变成了区间赋值+单点求和。每次1操作给区间y到y+k-1赋值x-y即可。

注意要判断当前位置是否被修改过。

AC代码

const int N = 1e5 + 50, MOD = 1e9 + 7;

int f[4 * N], lz[4 * N], a[N], b[N];
void push_down(int k,int l,int r)
{
    if (lz[k] < 1000000)
    {
        int m = (l + r) / 2;
        f[k + k] = lz[k];
        f[k + k + 1] = lz[k];
        lz[k + k] = lz[k + k + 1] = lz[k];
        lz[k] =  1000000;
    }
}
void revise(int k, int l, int r, int x, int y, int z)
{
    if (l == x && r == y)
    {
        f[k] =  z;
        lz[k] = z;
        return;
    }
    push_down(k, l, r);
    int m = (l + r) / 2;
    if (y <= m)revise(k + k, l, m, x, y, z);
    else
        if (x > m)revise(k + k + 1, m + 1, r, x, y, z);
        else
        {
            revise(k + k, l, m, x, m, z);
            revise(k + k + 1, m + 1, r, m + 1, y, z);
        }
}

int calc(int k, int l, int r, int x)
{
    if (l == r)return f[k];
    push_down(k, l, r);
    int m = (l + r) / 2;
    if (x <= m)return calc(k + k, l, m, x);
    else return calc(k + k + 1, m + 1, r, x);
}
void solve()
{
    int n, m, op, x, y, k;
    cin >> n >> m;
    //初始给偏移量打上一个很大的数
    memset(f, INF, sizeof f);
    memset(lz, INF, sizeof lz);
    for (int i = 1; i <= n; i++)cin >> a[i];
    for (int i = 1; i <= n; i++)cin >> b[i];
    while (m--)
    {
        cin >> op >> x;
        if (op == 1)
        {
            cin >> y >> k;
            //区间赋值偏移量
            revise(1, 1, n, y, y + k - 1, x - y);
        }
        else
        {
        	
            y = calc(1, 1, n, x);
            //如果偏移量是很大的数,说明这个位置还没被修改过,输出b数组
            if (y > 1000000)cout << b[x] << endl;
            else cout << a[x + y] << endl;
        }
    }
}