http://codeforces.com/problemset/problem/292/E
题目大意:两个数组,a和b,两种操作:
1:将数组a的区间[x,x+k-1]复制给数组b的区间[y,y+k-1]。
2:问当前b[x]的值。
思路:这道题可以用线段树做,在线段树中维护以下值:sta,stb,这两个值只有在线段树的叶子节点才有意义,对于一个位置po,(也就是线段[po,po],它是线段树的叶子节点),sta为0表示这个位置还没有被a覆盖,保持原来的值,否则,sta表示位置po已被覆盖,且是被a[sta]~a[sta+k-1]覆盖。stb为0和sta类似,不为0表示该位置是从stb开始被覆盖的。下面举个例子。
比如我们进行操作1,将a[x]~a[x+k-1]的值复制给数组b的区间[y,y+k-1],那么我们将线段树中区间[y,y+k-1]中的sta赋值为x,将stb赋值为y。
那么对于操作1,:1,x,y,k,我们就将区间[y,y+k-1]中的sta,stb分别赋值为x,y.
对于操作2:2,po 我们得到位置po的值为sta和stb,若sta为0,则输出b[po]即可,否则输出a[po-stb+sta]即可。
代码如下:
#include <iostream> #include <string.h> #include <algorithm> #include <stdio.h> #define maxn 100010 #define mid ((t[p].l+t[p].r)>>1) #define ls (p<<1) #define rs (ls|1) using namespace std; struct tree { int l,r; int sta,stb; }t[maxn<<2]; int a[maxn],b[maxn]; void pushdown(int p) { if(t[p].sta) { t[ls].sta=t[p].sta; t[ls].stb=t[p].stb; t[rs].sta=t[p].sta; t[rs].stb=t[p].stb; t[p].sta=0; } } void build(int p,int l,int r) { t[p].l=l,t[p].r=r,t[p].sta=t[p].stb=0; if(l==r) return; build(ls,l,mid); build(rs,mid+1,r); } void change(int p,int l,int r,int sta,int stb) { if(t[p].l==l&&t[p].r==r) { t[p].sta=sta; t[p].stb=stb; return; } pushdown(p); if(r<=mid) change(ls,l,r,sta,stb); else if(l>mid) change(rs,l,r,sta,stb); else { change(ls,l,mid,sta,stb); change(rs,mid+1,r,sta,stb); } } struct node { int sta,stb; }; node query(int p,int x) { node tmp; if(t[p].l==t[p].r) { tmp.sta=t[p].sta,tmp.stb=t[p].stb; return tmp; } pushdown(p); if(x>mid) return query(rs,x); return query(ls,x); } int main() { freopen("dd.txt","r",stdin); int n,q,i; scanf("%d%d",&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 t,x,y,z; scanf("%d",&t); if(t==1) { scanf("%d%d%d",&x,&y,&z); change(1,y,y+z-1,x,y); } else { scanf("%d",&x); node tmp=query(1,x); if(tmp.stb==0) printf("%d\n",b[x]); else printf("%d\n",a[x-tmp.stb+tmp.sta]); } } return 0; }