您的位置:首页 > 其它

[COGS2554][SYZOJ247][福利]可持久化线段树

2017-07-14 10:55 274 查看

思路:

主席树模板。

注意内存的分配,原始的线段树有$2n$个结点,每次更新时最多增加$log(n)$个结点,总共有$q$次询问,所以存储结点的数组大小为$2N+q log(n)$。

#include<cstdio>
#include<cctype>
#include<vector>
#include<algorithm>
inline int getint() {
char ch;
while(!isdigit(ch=getchar()));
int x=ch^'0';
while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
return x;
}
const int N=10001,Q=100001,logN=100;
class FotileTree {
private:
unsigned int left[(N<<1)+Q*logN],right[(N<<1)+Q*logN];
std::vector<int> val;
void push_up(const int p) {
val

=std::max(val[left[p]],val[right[p]]); } public: unsigned int root[Q]; unsigned int newnode() { val.push_back(0); return val.size()-1; } void build(const int p,const int b,const int e) { if(b==e) { val[p]=getint(); return; } int mid=(b+e)>>1; build(left[p]=newnode(),b,mid); build(right[p]=newnode(),mid+1,e); push_up(p); } unsigned int modify(const int p,const int b,const int e,const int x,const int y) { unsigned int new_p=newnode(); if(b==e) { val[new_p]=y; return new_p; } int mid=(b+e)>>1; if(x<=mid) left[new_p]=modify(left[p],b,mid,x,y),right[new_p]=right[p]; if(x>mid) right[new_p]=modify(right[p],mid+1,e,x,y),left[new_p]=left[p]; push_up(new_p); return new_p; } int query(const int p,const int b,const int e,const int l,const int r) { if((b==l)&&(e==r)) return val[p]; int mid=(b+e)>>1; int ans=0; if(l<=mid) ans=std::max(ans,query(left[p],b,mid,l,std::min(mid,r))); if(r>mid) ans=std::max(ans,query(right[p],mid+1,e,std::max(mid+1,l),r)); return ans; } }; FotileTree t; int main() { freopen("longterm_segtree.in","r+",stdin); freopen("longterm_segtree.out","w+",stdout); int n=getint(),q=getint(),ver=0; t.build(t.root[++ver]=t.newnode(),1,n); while(q--) { int op=getint(),k=getint(),x=getint(),y=getint(); if(!op) printf("%d\n",t.query(t.root[k],1,n,x,y)); if(op) t.root[++ver]=t.modify(t.root[k],1,n,x,y); } fclose(stdin),fclose(stdout); return 0; }

[p] 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: