Codeforces 292E(Copying Data)

题意:给出两个数组A,B,每次操作从将从A数组第x个位置开始的k个元素复制到B数组第y个位置(覆盖B数组的k个元素),然后询问B数组的某个下标的值

思路:普通的线段树,实现区间修改,单点查询就行了,线段树结点储存A数组在这区间的开始结束位置



#include <set>
#include <map>
#include <cmath>
#include <stack>
#include <queue>
#include <string>
#include <vector>
#include <cstdio>
#include <climits>
#include <cstring>
#include <iostream>
#include <algorithm>
#define  LL long long
#define  pub push_back
#define  inst insert
#define  mp make_pair
#define  SZ(x) ((int)(x).size())
#define  ForEach(i,c) for(__typeof((c).begin()) i = (c).begin();i != (c).end();i++)
using namespace std;

const int N = 100010;
int A[N], B[N], res;
struct segTree{
	int lc, rc, start, end, flag;
}arr[N * 4];

inline int lson(int idx){
	return (idx << 1);
}
inline int rson(int idx){
	return ((idx << 1) | 1);
}

void pushDown(int idx){
	if(arr[idx].flag){
		arr[lson(idx)].start = arr[idx].start;
		arr[lson(idx)].end = (arr[idx].start + arr[idx].end) / 2;
		arr[lson(idx)].flag = 1;
		arr[rson(idx)].start = (arr[idx].start + arr[idx].end) / 2 + 1;
		arr[rson(idx)].end = arr[idx].end;
		arr[rson(idx)].flag = 1;	
		arr[idx].flag = 0;
	}	
}

void build(int idx, int l, int r){
	arr[idx].lc = l, arr[idx].rc = r;
	arr[idx].flag = 0;
	if(l == r)
		return ;
	int mid = (l + r) >> 1;
	build(lson(idx), l, mid);
	build(rson(idx), mid + 1, r);	
}

void update(int idx, int x, int y, int len){
	int l = y, r = y + len - 1;
	if(arr[idx].lc > r || l > arr[idx].rc)
		return ;
	if(arr[idx].lc >= l && arr[idx].rc <= r){
		arr[idx].flag = 1;
		arr[idx].start = x + arr[idx].lc - y;
		arr[idx].end = x + arr[idx].rc - y;
		return ;
	}
	if(arr[idx].lc == arr[idx].rc)
		return ;
	pushDown(idx);
	update(lson(idx), x, y, len);
	update(rson(idx), x, y, len);
}

void query(int idx, int loc){
	if(arr[idx].lc == arr[idx].rc){
		if(arr[idx].lc == loc){
			if(arr[idx].flag == 0)
				res = N;
			else
				res = arr[idx].start;
		}
		return ;		
	}
	pushDown(idx);
	if(arr[lson(idx)].rc >= loc)
		query(lson(idx), loc);
	else
		query(rson(idx), loc);
}

int main(){
	int n, q, i;	
	cin >> n >> q;
	for(i = 1;i <= n;i++)
		scanf("%d", &A[i]);
	for(i = 1;i <= n;i++)
		scanf("%d", &B[i]);
	build(1, 1, n);
	while(q--){
		int ord, x, y, k;
		scanf("%d", &ord);
		if(ord == 1){
			scanf("%d%d%d", &x, &y, &k);
			update(1, x, y, k);
		} else {
			scanf("%d", &x);
			query(1, x);
			if(res == N)
				printf("%d\n", B[x]);
			else
				printf("%d\n", A[res]);
		}
	}
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值