【BZOJ 1146】【CTSC 2008】网络管理network
来源:互联网 发布:mac电脑免费翻墙 编辑:程序博客网 时间:2024/06/05 17:28
一句话题意,树链上带修改区间第k大
感觉可以dfs+主席树
于是写的线段树套平衡树+链剖+二分(修改
这里简单介绍一下区间第K大做法,对于每个线段树所”管辖“的范围,建一棵相应范围内的平衡树(我用的Treap);修改时,修改每个包含被修改节点的线段树节点所对应的Treap;查询时,二分
答案,统计每个区间内比当前答案小的数即可(为了保证是序列里的数,我们可以二分答案在原序列中排名)
PS:这题真的是第K大,不是排名第K的,被坑WA了一次= =
code:
#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#define mid (l+r)/2#define lch i<<1,l,mid#define rch i<<1|1,mid+1,rusing 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() {if (left) return left->size; else return 0;} int rsize() {if (right) return right->size; else return 0;} 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);} } } else p->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 i,int l,int r,int x,int y,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 Qsum(int x,int y){ 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 x,int y,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 x,int y,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("%d%d%d",&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); }}
1 0
- 【BZOJ 1146】【CTSC 2008】网络管理network
- BZOJ 1146 CTSC 2008 网络管理 Network 树链剖分+二分答案+平衡树
- bzoj-1146 网络管理Network
- 【BZOJ 1146】 [CTSC2008]网络管理Network
- 【树链剖分】【bzoj 1146】: [CTSC2008]网络管理Network
- bzoj 1146: [CTSC2008]网络管理Network
- 【主席树】BZOJ 1146 network网络管理
- [BZOJ 1146] [CTSC2008]网络管理Network
- BZOJ 1146 [CTSC2008]网络管理Network
- BZOJ 1146: [CTSC2008]网络管理Network
- 【CTSC 2008】 网络管理 --树链剖分+树状数组+Trie树
- 【BZOJ 1148】【CTSC 2008】挂缀【BZOJ 1 148】【CTSC 2008】挂缀
- [主席树 树状数组套权值线段树] BZOJ 1146 [CTSC2008]网络管理Network
- BZOJ 1146: [CTSC2008]网络管理Network 【树上带修改主席树】
- BZOJ 1145 [CTSC 2008] 树状数组+组合数学
- BZOJ 1146: [CTSC2008]网络管理Network 树链剖分 树状数组套主席树/线段树套平衡树
- 网络管理Network
- 【BZOJ】【P1146】【CTSC2008】【网络管理Network】【题解】【树链剖分+线段树套平衡树】
- GDB十分钟教程
- HDU5285.wyh2000 and pupil
- 关于寄存器ESP和EBP
- Spring经典面试题
- zoj2987 Misspelling
- 【BZOJ 1146】【CTSC 2008】网络管理network
- mariaDB 创建存储过程时报错
- UVa 1629 - Cake slicing(记忆化搜索)
- Java栈与堆
- poj3278Catch That Cow(bfs)
- HDU1560 DNA sequence (IDA*)
- 如何从wireshark中获取H264码流(原创)
- 【cogs58】延绵的山峰【st表】
- 取模运算的性质