思路:
主席树模板。
注意内存的分配,原始的线段树有$2n$个结点,每次更新时最多增加$log(n)$个结点,总共有$q$次询问,所以存储结点的数组大小为$2N+q log(n)$。
1 #include<cstdio> 2 #include<cctype> 3 #include<vector> 4 #include<algorithm> 5 inline int getint() { 6 char ch; 7 while(!isdigit(ch=getchar())); 8 int x=ch^'0'; 9 while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0'); 10 return x; 11 } 12 const int N=10001,Q=100001,logN=100; 13 class FotileTree { 14 private: 15 unsigned int left[(N<<1)+Q*logN],right[(N<<1)+Q*logN]; 16 std::vector<int> val; 17 void push_up(const int p) { 18 val[p]=std::max(val[left[p]],val[right[p]]); 19 } 20 public: 21 unsigned int root[Q]; 22 unsigned int newnode() { 23 val.push_back(0); 24 return val.size()-1; 25 } 26 void build(const int p,const int b,const int e) { 27 if(b==e) { 28 val[p]=getint(); 29 return; 30 } 31 int mid=(b+e)>>1; 32 build(left[p]=newnode(),b,mid); 33 build(right[p]=newnode(),mid+1,e); 34 push_up(p); 35 } 36 unsigned int modify(const int p,const int b,const int e,const int x,const int y) { 37 unsigned int new_p=newnode(); 38 if(b==e) { 39 val[new_p]=y; 40 return new_p; 41 } 42 int mid=(b+e)>>1; 43 if(x<=mid) left[new_p]=modify(left[p],b,mid,x,y),right[new_p]=right[p]; 44 if(x>mid) right[new_p]=modify(right[p],mid+1,e,x,y),left[new_p]=left[p]; 45 push_up(new_p); 46 return new_p; 47 } 48 int query(const int p,const int b,const int e,const int l,const int r) { 49 if((b==l)&&(e==r)) return val[p]; 50 int mid=(b+e)>>1; 51 int ans=0; 52 if(l<=mid) ans=std::max(ans,query(left[p],b,mid,l,std::min(mid,r))); 53 if(r>mid) ans=std::max(ans,query(right[p],mid+1,e,std::max(mid+1,l),r)); 54 return ans; 55 } 56 }; 57 FotileTree t; 58 int main() { 59 freopen("longterm_segtree.in","r+",stdin); 60 freopen("longterm_segtree.out","w+",stdout); 61 int n=getint(),q=getint(),ver=0; 62 t.build(t.root[++ver]=t.newnode(),1,n); 63 while(q--) { 64 int op=getint(),k=getint(),x=getint(),y=getint(); 65 if(!op) printf("%d\n",t.query(t.root[k],1,n,x,y)); 66 if(op) t.root[++ver]=t.modify(t.root[k],1,n,x,y); 67 } 68 fclose(stdin),fclose(stdout); 69 return 0; 70 }