bzoj 1146 - Network
来源:互联网 发布:ubuntu arm 国内源 编辑:程序博客网 时间:2024/05/16 19:39
昨晚写代码的时候就预料到这次debug要好久。。。果然,下午debug了4个小时,还是sb错误,不能忍,简直就是自己给自己挖了个坑,那么问题来了。。。
树上的区间第k大,树链剖分先做好。查询的时候,比如u到v上的第k大,我们先二分这个第K大的值,再统计u,v路径上的比二分的这个值大的有多少,然后比较;确定u,v上比val大的数目时,可以利用树状数组思想,建立n个treap树,统计树上比这个值大的有多少,具体来说就是num_bigger_than[u]-num_bigger_than[v-1];调整的时候,就要按照树状数组的方法,对每个相关的树去更新。
#include <cstdio>#include <cstdlib>#include <cstring>#include <iostream>using namespace std;const int maxn=80010;//treap beginsstruct Node{ Node *ch[2]; // 左右子树 int r; // 随机优先级 int v; // 值 int s; Node(int v):v(v) { ch[0] = ch[1] = NULL; r = rand(); s = 1; } int cmp(int x) const { if (x == v) return -1; return x < v ? 0 : 1; } void maintain() { s = 1; if(ch[0] != NULL) s += ch[0]->s; if(ch[1] != NULL) s += ch[1]->s; }};void Rotate(Node* &o, int d){ Node* k = o->ch[d^1]; o->ch[d^1] = k->ch[d]; k->ch[d] = o; o->maintain(); k->maintain(); o = k;}void Insert(Node* &o, int x){ if(o == NULL) o = new Node(x); else { int d = (x < o->v ? 0 : 1); Insert(o->ch[d], x); if(o->ch[d]->r > o->r) Rotate(o, d^1); } o->maintain();}void Remove(Node* &o, int x){ int d = o->cmp(x); int ret = 0; if(d == -1) { Node* u = o; if(o->ch[0] != NULL && o->ch[1] != NULL) { int d2 = (o->ch[0]->r > o->ch[1]->r ? 1 : 0); Rotate(o, d2); Remove(o->ch[d2], x); } else { if(o->ch[0] == NULL) o = o->ch[1]; else o = o->ch[0]; delete u; } } else Remove(o->ch[d], x); if(o != NULL) o->maintain();}int kth(Node *o,int k){ if(o==NULL||k<=0||k>o->s) return 0; int s=(o->ch[1]==NULL?0:o->ch[1]->s); if(k==s+1) return o->v; else if(k<=s) return kth(o->ch[1],k); else return kth(o->ch[0],k-s-1);}int upper1(const Node *t,int val) //第t棵树上比val大的有多少{ if(t==NULL) return 0; int tmp=t->v,res=0; if(tmp==val) { res++; res+=upper1(t->ch[0],val); res+=upper1(t->ch[1],val); } else if(tmp>val) { res++; if(t->ch[1]!=NULL) res+=t->ch[1]->s; res+=upper1(t->ch[0],val); } else res+=upper1(t->ch[1],val); return res;}Node *root[maxn];//ends,about the questionstruct EdgeNode{ int to,next;} edge[maxn*2];int w[maxn],head[maxn],top[maxn],fa[maxn], dep[maxn],num[maxn],idx[maxn],son[maxn];int cnt,pos,n;inline void add_edge(int u,int v){ edge[cnt].to=v,edge[cnt].next=head[u]; head[u]=cnt++; edge[cnt].to=u,edge[cnt].next=head[v]; head[v]=cnt++;}void dfs(int u,int pre,int d){ dep[u]=d,fa[u]=pre,num[u]=1; for(int k=head[u]; k!=-1; k=edge[k].next) { int v=edge[k].to; if(v==pre) continue; dfs(v,u,d+1); num[u]+=num[v]; if(son[u]==-1||num[v]>num[son[u]]) son[u]=v; }}void build_tree(int u,int tp){ top[u]=tp,idx[u]=++pos; if(son[u]==-1) return; build_tree(son[u],tp); for(int k=head[u]; k!=-1; k=edge[k].next) { int v=edge[k].to; if(v!=son[u]&&v!=fa[u]) build_tree(v,v); }}int lca(int u,int v){ while(top[u]!=top[v]) { if(dep[top[u]]<dep[top[v]]) swap(u,v); u=fa[top[u]]; } if(dep[u]>dep[v]) swap(u,v); return u;}int gao(int l,int r,int val) //l->r区间上比val大的一共有多少{ int ans=0; int k=r; while(k) { ans+=upper1(root[k],val); k-=k&(-k); } k=l-1; while(k) { ans-=upper1(root[k],val); k-=k&(-k); } return ans;}void modify(int u,int val){ if(w[u]==val) return; int k=idx[u]; while(k<=n) { Remove(root[k],w[u]); Insert(root[k],val); k+=k&(-k); } Remove(root[maxn-1],w[u]); Insert(root[maxn-1],val); w[u]=val;}int great(int u,int v,int val) //统计u->v上比val大的一共有多少{ int ql,qr,ans=0; while(top[u]!=top[v]) { if(dep[top[u]]<dep[top[v]]) swap(u,v); ql=idx[top[u]],qr=idx[u]; ans+=gao(ql,qr,val); u=fa[top[u]]; } if(dep[u]>dep[v]) swap(u,v); ans+=gao(idx[u],idx[v],val); return ans;}int qurey(int u,int v,int k){ int pa=lca(u,v); if(dep[u]+dep[v]-2*dep[pa]+1<k) return -1; int l=1,r=n; while(l<=r) { int mid=l+r>>1; int tmp=kth(root[maxn-1],mid); //二分val值 if(great(u,v,tmp)>=k) r=mid-1; else l=mid+1; } return kth(root[maxn-1],l);}int main(){ int m; while(scanf("%d%d",&n,&m)!=EOF) { cnt=pos=0; memset(head,-1,sizeof(head)); memset(son,-1,sizeof(son)); for(int i=0; i<maxn; i++) root[i]=NULL; for(int i=1; i<=n; i++) scanf("%d",&w[i]); for(int i=1; i<n; i++) { int u,v; scanf("%d%d",&u,&v); add_edge(u,v); } dfs(1,1,1); build_tree(1,1); for(int i=1; i<=n; i++) { int p=idx[i]; Insert(root[maxn-1],w[i]); while(p<=n) { Insert(root[p],w[i]); p+=p&(-p); //树状数组思想 } } for(int i=1; i<=m; i++) { int k,a,b; scanf("%d%d%d",&k,&a,&b); if(!k) modify(a,b); else { int ans=qurey(a,b,k); if(ans==-1) printf("invalid request!\n"); else printf("%d\n",ans); } } } return 0;}
0 0
- bzoj 1146 - Network
- bzoj-1146 网络管理Network
- 【BZOJ 1146】 [CTSC2008]网络管理Network
- 【树链剖分】【bzoj 1146】: [CTSC2008]网络管理Network
- bzoj 1146: [CTSC2008]网络管理Network
- 【BZOJ 1146】【CTSC 2008】网络管理network
- 【主席树】BZOJ 1146 network网络管理
- [BZOJ 1146] [CTSC2008]网络管理Network
- BZOJ 1146 [CTSC2008]网络管理Network
- BZOJ 1146: [CTSC2008]网络管理Network
- 【bzoj 3732】Network
- BZOJ P3732 Network
- BZOJ 3732: Network
- BZOJ 3732: Network
- BZOJ 3732 Network Kruskal重构树
- [bzoj 4080] Wf2014 Sensor Network
- BZOJ 3732: Network|Kruskal|Lca
- BZOJ 3732: Network|动态树
- git 图解Git/图形化的Git参考手册
- VS2005下编译Lua源代码
- 使用INTERVAL DAY TO SECOND类型
- 实验一: VC编程工具的灵活使用
- andorid cocos2d 游戏开发入门学习经验之总结
- bzoj 1146 - Network
- PMP考试的过与不过
- Android Shape绘制实用圆圈
- 排序——插入,快速排序
- HDU 5009 Paint Pearls (动态规划)
- tomcat日志配置详解
- printf vprintf
- sql注入总结
- git 分支管理策略