【BZOJ 1146】【CTSC 2008】网络管理network

一句话题意,树链上带修改区间第k大 感觉可以dfs+主席树过掉,但我不会写= = 于是写的线段树套平衡树+链剖+二分(修改慢了好多啊QAQ) 这里简单介绍一下区间第K大做法,对于每个线段树所”管辖“的范围,,建一棵相应范围内的平衡树(我用的Treap);修改时,修改每个包含被修改节点的线段树节点所对应的Treap;查询时,二分 答案,统计每个区间内比当前答案小的数即可(为了保证是序列里的数,我们可以二分答案在原序列中排名) PS:这题真的是第K大,不是排名第K的,被坑WA了一次= = code:

using namespace std;struct treap_node{treap_node *left,*right;int val,fix,size,wgt;treap_node(int val): val(val) {size=1; wgt=1; left=right=NULL; fix=rand();}int lsize(){;}int rsize(){;}void Maintain(){size=wgt; size+=lsize()+rsize();}};treap_node *seg[320001];int f[80001],plc[80001];int point[80001],next[200001];struct hp{int u,v;}ai[200001];struct hq{int dep,fat,top,size,wson;}tree[80001];int n,a[80001],ans,m,totw,e=0;void tlr(treap_node *&a){treap_node *b=a->right;a->right=b->left; b->left=a;a->Maintain(); b->Maintain(); a=b;}void trr(treap_node *&a){treap_node *b=a->left;a->left=b->right; b->right=a;a->Maintain(); b->Maintain(); a=b;}void add(int u,int v){e++; ai[e].u=u; ai[e].v=v; next[e]=point[u]; point[u]=e;e++; ai[e].v=u; ai[e].v=u; next[e]=point[v]; point[v]=e;}void insert(treap_node *&p,int value) {if (!p)p=new treap_node(value);else{if (value==p->val)p->wgt++;if (value<p->val){insert(p->left,value);if (p->left->fix<p->fix)trr(p);}if (value>p->val){insert(p->right,value);if (p->right->fix<p->fix)tlr(p);}}p->Maintain(); }void make_node(int i,int l,int r){int j;for (j=l;j<=r;++j)insert(seg[i],a[f[j]]);}void build(int i,int l,int r){make_node(i,l,r);if (l==r) return;build(lch); build(rch);}void build_tree(int now,int last,int depth){int i;tree[now].fat=last;tree[now].dep=depth;tree[now].size=1;tree[now].wson=0;for (i=point[now];i;i=next[i])if (ai[i].v!=last){build_tree(ai[i].v,now,depth+1);tree[now].size+=tree[ai[i].v].size;if (tree[ai[i].v].size>tree[tree[now].wson].size)tree[now].wson=ai[i].v;}}void build_seg(int now,int tp){int i;tree[now].top=tp;plc[now]=++totw; f[totw]=now;if (tree[now].wson!=0)build_seg(tree[now].wson,tp);for (i=point[now];i;i=next[i])if (ai[i].v!=tree[now].wson&&ai[i].v!=tree[now].fat)build_seg(ai[i].v,ai[i].v);}void del(treap_node *&p,int val){if (val==p->val){if (p->wgt==1){if (!p->left||!p->right){if (!p->left) p=p->right;else p=p->left;}else{if (p->left->fix<p->right->fix){trr(p); del(p->right,val);}else{tlr(p); del(p->left,val);}}}elsep->wgt–;}else{if (val<p->val) del(p->left,val);else del(p->right,val);}if (p!=NULL) p->Maintain(); }int kth(treap_node *p,int k){if (k<=p->lsize()) return kth(p->left,k);if (k>p->lsize()+p->wgt) return kth(p->right,k-p->lsize()-p->wgt);if (k<=p->lsize()+p->wgt) return p->val;}int rank(treap_node *p,int val,int cur){if (val==p->val) return cur+p->lsize();if (val>p->val&&!p->right) return cur+p->lsize()+p->wgt;if (val<p->val&&!p->left) return cur;if (val<p->val) return rank(p->left,val,cur);if (val>p->val) return rank(p->right,val,cur+p->lsize()+p->wgt);}void query(,int val){if (x<=l&&y>=r){ans+=rank(seg[i],val,0);return;}if (x<=mid) query(lch,x,y,val);if (y>mid) query(rch,x,y,val);}void delt(int i,int l,int r,int x,int num){if (l==x&&l==r){del(seg[i],num);return;}del(seg[i],num);if (x<=mid) delt(lch,x,num);else delt(rch,x,num);}void ins(int i,int l,int r,int x,int num){if (l==x&&l==r){insert(seg[i],num);return;}insert(seg[i],num);if (x<=mid) ins(lch,x,num);else ins(rch,x,num);}){int t=0,f1=tree[x].top,f2=tree[y].top;while (f1!=f2){//cout<<x<<‘ ‘<<y<<‘ ‘<<f1<<‘ ‘<<f2<<endl;if (tree[f1].dep<tree[f2].dep) {swap(x,y); swap(f1,f2);}t+=plc[x]-plc[f1]+1;x=tree[f1].fat; f1=tree[x].top;}if (tree[x].dep>tree[y].dep) swap(x,y);t+=plc[y]-plc[x]+1;return t;}void Q(,int num){int f1=tree[x].top,f2=tree[y].top;while (f1!=f2){if (tree[f1].dep<tree[f2].dep) {swap(x,y); swap(f1,f2);}query(1,1,n,plc[f1],plc[x],num);x=tree[f1].fat; f1=tree[x].top;}if (tree[x].dep>tree[y].dep) swap(x,y);query(1,1,n,plc[x],plc[y],num);}void work(,int k){int l,r,t,midx,len;l=1; r=n;len=Qsum(x,y);if (k>len) {printf(“invalid request!\n”); return;}k=len-k+1;while (l<r){midx=(l+r+1)/2;t=kth(seg[1],midx);ans=0; Q(x,y,t);if (ans<=k-1) l=midx;else r=midx-1;}printf(“%d\n”,kth(seg[1],l));}int main(){int i,x,y,k;scanf(“%d%d”,&n,&m);for (i=1;i<=n;++i)scanf(“%d”,&a[i]);for (i=1;i<n;++i){scanf(“%d%d”,&x,&y);add(x,y);}build_tree(1,0,0);build_seg(1,1);build(1,1,n);for (i=1;i<=m;++i){scanf(“,&k,&x,&y);if (k==0){delt(1,1,n,plc[x],a[x]);ins(1,1,n,plc[x],y);a[x]=y;}if (k>0)work(x,y,k);}}

一错再错,把握正确的方向,

【BZOJ 1146】【CTSC 2008】网络管理network

相关文章:

你感兴趣的文章:

标签云: