主席树
2015-06-06 19:06
309 查看
主席树
好神的数据结构,不过挺好写的。。POJ 2104 K-th number
题目大意:
对一静态序列,每次询问[l,r]中第k大d
主席树模板题
贴代码:
#include<cstdio> #include<iostream> #include<algorithm> #define M 100010 using namespace std; struct Node{ int l,r,s; }a[M*50]; int id[M],d[M],cnt,key; void update(int l,int r,int &pos) { a[++cnt]=a[pos]; pos=cnt; ++a[pos].s; if(l==r) return ; int m=(l+r)/2; if(key<=m) update(l,m,a[pos].l); else update(m+1,r,a[pos].r); } int query(int l,int r,int x,int y,int k) { if(l==r) return l; int mid=(l+r)/2,s=a[a[y].l].s-a[a[x].l].s; if(k<=s) return query(l,mid,a[x].l,a[y].l,k); else return query(mid+1,r,a[x].r,a[y].r,k-s); } bool cmp(int x,int y) { return d[x]<d[y]; } int n,m; int b[M]; int root[M]; int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) scanf("%d",&d[i]),id[i]=i; sort(id+1,id+n+1,cmp); for(int i=1;i<=n;i++) b[id[i]]=i; for(int i=1;i<=n;i++) { root[i]=root[i-1]; key=b[i]; update(1,n,root[i]); } int x,y; for(int i=1;i<=m;i++) { scanf("%d%d%d",&x,&y,&key); int td=query(1,n,root[x-1],root[y],key); printf("%d\n",d[id]); } return 0; }
HDU 4417 Super Mario
题目大意:
对于一静态序列,询问[l,r]中小于x的个数
这题有树状数组解法,不过我用二分+主席树过了,
(跑得也很快,BIT 200+ms 二分+主席树 500+ms#include<cstdio> #include<iostream> #include<cstring> #include<algorithm> #define M 100010 using namespace std; int d[M],b[M],id[M],root[M],cnt,key,T,n,m; struct Node{ int l,r,s; }a[M*30]; bool cmp (int x,int y) { return d[x]<d[y]; } void update(int &t,int l,int r) { a[++cnt]=a[t]; t=cnt; ++a[t].s; if(l==r) return ; int mid=(l+r)/2; if(key<=mid) update(a[t].l,l,mid); else update(a[t].r,mid+1,r); } int query(int l,int r,int x,int y,int k) { if(l==r) return l; int mid=(l+r)/2,s=a[a[y].l].s-a[a[x].l].s; if(k<=s) return query(l,mid,a[x].l,a[y].l,k); else return query(mid+1,r,a[x].r,a[y].r,k-s); } int main() { scanf("%d",&T); for(int cas=1;cas<=T;cas++) { scanf("%d%d",&n,&m); printf("Case %d:\n",cas); for(int i=1;i<=n;i++) scanf("%d",&d[i]),id[i]=i; sort(id+1,id+n+1,cmp); for(int i=1;i<=n;i++) b[id[i]]=i; for(int i=1;i<=n;i++) { root[i]=root[i-1]; key=b[i]; update(root[i],1,n); } for(int i=1,x,y;i<=m;i++) { scanf("%d%d%d",&x,&y,&key); x++,y++; if(d[id[query(1,n,root[x-1],root[y],y-x+1)]]<=key) { printf("%d\n",y-x+1); } else if(d[id[query(1,n,root[x-1],root[y],1)]]>key) { printf("0\n"); } else { int l=0,r=y-x+1; int ans=0,mid; while(l<=r) { int mid=(l+r)/2; if(d[id[query(1,n,root[x-1],root[y],mid)]]<=key) l=mid+1,ans=mid; else r=mid-1; } printf("%d\n",ans); } } } return 0; }
SPOJ COT Count on a tree
s=s(lson[u])+s(lson[v])-2*s(lson[lca])
记住如果lca 在[l,mid] 中 s要+1#include<cstdio> #include<iostream> #include<algorithm> #include<cstring> #include<vector> #define M 100005 using namespace std; int g[M]; struct Edge { int nxt,v; } e[M*2]; struct Node { int l,r,s; } a[M*20]; vector<pair<int ,int > > q[M]; int cnt,num,key,n,m; int p[M],fa[M],id[M],d[M],b[M],root[M]; int from[M],to[M],val[M]; void add(int u,int v) { e[++cnt].nxt=g[u],e[cnt].v=v,g[u]=cnt; e[++cnt].nxt=g[v],e[cnt].v=u,g[v]=cnt; } void update(int &t,int l,int r) { a[++num]=a[t]; t=num; ++a[t].s; if(l==r) return ; int mid=(l+r)/2; if(key<=mid) update(a[t].l,l,mid); else update(a[t].r,mid+1,r); } int ifind(int x) { return p[x] == x ? x : p[x]=ifind(p[x]); } bool vis[M]; int lca[M]; void dfs(int x) { // cout<<x<<endl; p[x]=x; key=b[x]; root[x]=root[fa[x]]; update(root[x],1,n); for(int i=g[x]; i; i=e[i].nxt) if(e[i].v!=fa[x]) { //cout<<e[i].v<<endl; fa[e[i].v]=x; dfs(e[i].v); p[e[i].v]=x; } vis[x]=1; int t=q[x].size(); for(int i=0; i<t; ++i) if(vis[q[x][i].first]) { lca[q[x][i].second]=ifind(q[x][i].first); } } bool cmp(int x,int y) { return d[x]<d[y]; } int getans(int l,int r,int x,int y,int f,int k) { if(l==r) return l; int mid=(l+r)/2,s=a[a[x].l].s+a[a[y].l].s-(a[a[f].l].s<<1); if(b[key]>=l && b[key]<=mid) ++s; if(k<=s) return getans(l,mid,a[x].l,a[y].l,a[f].l,k); else return getans(mid+1,r,a[x].r,a[y].r,a[f].r,k-s); } int main() { scanf("%d%d",&n,&m); for(int i=1; i<=n; i++) scanf("%d",&d[i]),id[i]=i; sort(id+1,id+n+1,cmp); for(int i=1; i<=n; i++) b[id[i]]=i; for(int i=1,x,y; i<n; i++) { scanf("%d%d",&x,&y); add(x,y); } for(int i=1; i<=m; ++i) { scanf("%d%d%d",&from[i],&to[i],&val[i]); q[from[i]].push_back(pair<int, int> (to[i], i)); q[to[i]].push_back(pair<int, int> (from[i], i)); } dfs(1); for(int i=1; i<=m; ++i) { if(from[i]==to[i]) { printf("%d\n", d[from[i]]); continue; } key=lca[i]; printf("%d\n", d[id[getans(1, n, root[from[i]], root[to[i]], root[key], val[i])]]); //被root[ff]坑了一早上,写成了ff。唉 } return 0; }相关文章推荐
- discuz限制用户查看购买记录
- 6种比较排序和决策树
- 苹果开发 笔记(35)音频
- Struts2学习笔记1
- Java面向对象小记(1)
- 我的Cocos2d-x学习笔记(二十)音乐与音效
- 手机滑动效果探索
- Android UI系列中的Dialog,包括DatePickerDialog、TimePickerDialog、Toasts以及ProgressDialog
- log4j详解与实战
- 用strtok函数分割字符串
- bzoj 3211 线段树
- POJ 3723 Conscription
- Unity3D资源管理架构
- discuz登录admin后台老是自动跳出来
- 深度学习-LeCun、Bengio和Hinton的联合综述(下)
- C#高级编程第二天
- OC中View生命周期
- 新手学习编程的最佳方式
- Lemon OA第2篇:功能解析方法
- Discuz!X3.2 uc_server密码正确无法登录的解决方法