bzoj4448 [Scoi2015]情报传递 树链剖分+树状数组
来源:互联网 发布:软件销售代理协议 编辑:程序博客网 时间:2024/06/05 23:47
题目大意:
维护一颗树,支持一下操作(可以离线)
1、给一个点赋值;
2、查询一条链上比有多少个点以及某个数(i-c)小的点有多少个。
(我这个题目大意略精简了一点哈=。=,但是还是可以比较轻松的把原题目转化成这个意思的)
题目分析:
我们可以把所有的操作离线出来,把赋值操作按照赋值的大小排序(相当于没排,不知道我这个沙茶为毛要排一下>_<)
然后把所有的询问按照要(i-c)从小到大排序。
树链剖分一下,用树状数组维护dfs序。
扫一遍所有的询问,把小于询问权值的赋值操作的位置在dfs序中改为1。
然后查询树链上1的个数就可以了。
时间复杂度O(mlog^2n)
代码如下:
#include <cstdio>#include <algorithm>#include <iostream>#define N 220000using namespace std;inline int lowbit(int x){ return x&-x; }int n,m,root,sum,cnt;int fir[N],nes[N],v[N],tot=1;int fa[N],dep[N],son[N],sz[N],pos[N],ld[N],top;int fw[N],ans[N],_ans[N];bool mark[N];struct Change{ int x,id; bool operator < (const Change &c) const { return id<c.id; }}a[N];struct Query{ int x,y,c,id; bool operator < (const Query &a) const { return c<a.c; }}q[N];void edge(int x,int y){ v[++tot]=y; nes[tot]=fir[x]; fir[x]=tot;}void update(int x){ for(;x<=n;x+=lowbit(x)) fw[x]++;}int query(int l,int r){ int ans=0; for(;r;r-=lowbit(r)) ans+=fw[r]; for(l--;l;l-=lowbit(l)) ans-=fw[l]; return ans;}void dfs1(int c){ dep[c]=dep[fa[c]]+1; sz[c]=1; son[c]=0; for(int t=fir[c];t;t=nes[t]) { dfs1(v[t]); sz[c]+=sz[v[t]]; if(sz[v[t]]>sz[son[c]]) son[c]=v[t]; }}void dfs2(int c){ pos[c]=++top; ld[c]=c; if(son[fa[c]]==c) ld[c]=ld[fa[c]]; if(son[c]) dfs2(son[c]); for(int t=fir[c];t;t=nes[t]) { if(v[t]==son[c]) continue; dfs2(v[t]); }}void solve(int c){ int x=q[c].x,y=q[c].y; int id=q[c].id; while(ld[x]!=ld[y]) { if(dep[ld[x]]<dep[ld[y]]) swap(x,y); ans[id]+=pos[x]-pos[ld[x]]+1; _ans[id]+=query(pos[ld[x]],pos[x]); x=fa[ld[x]]; } if(dep[x]<dep[y]) swap(x,y); ans[id]+=pos[x]-pos[y]+1; _ans[id]+=query(pos[y],pos[x]);}int main(){ scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%d",&fa[i]); if(fa[i]==0) root=i; else edge(fa[i],i); } dfs1(root); dfs2(root); scanf("%d",&m); for(int i=1,opt,x,y,z;i<=m;i++) { scanf("%d",&opt); if(opt==1) { cnt++; scanf("%d%d%d",&q[cnt].x,&q[cnt].y,&q[cnt].c); q[cnt].id=cnt; q[cnt].c=i-q[cnt].c; } else { scanf("%d",&x); if(!mark[x]) { sum++; if(!mark[x]) mark[x]=true; a[sum].x=x; a[sum].id=i; } } } sort(a+1,a+sum+1); sort(q+1,q+cnt+1); int now=1; for(int i=1;i<=cnt;i++) { while(now<=sum && a[now].id<q[i].c) update(pos[a[now].x]),now++; solve(i); } for(int i=1;i<=cnt;i++) printf("%d %d\n",ans[i],_ans[i]); return 0;}
阅读全文
0 0
- bzoj4448 [Scoi2015]情报传递 树链剖分+树状数组
- bzoj4448: [Scoi2015]情报传递
- 【bzoj4448】【SCOI2015】情报传递
- [BZOJ4448][Scoi2015]情报传递(树上主席树)
- [BZOJ4448][Scoi2015]情报传递(树上主席树)
- bzoj 4448: [Scoi2015]情报传递 dfs序列&树状数组
- 【bzoj 4448】 [Scoi2015]情报传递 离线+树剖+树状数组
- 【Bzoj4448】情报传递
- 【BZOJ 4448】 [Scoi2015]情报传递|树链剖分|树套树
- 4448: [Scoi2015]情报传递
- bzoj 4448: [Scoi2015]情报传递
- 4448: [Scoi2015]情报传递 dfs序+主席树
- 4448: [Scoi2015]情报传递|主席树|离线操作
- 【BZOJ 4448】 [Scoi2015]情报传递|倍增LCA|主席树
- bzoj 4448: [Scoi2015]情报传递 (树上主席树)
- BZOJ 4448: [Scoi2015]情报传递 树剖套主席树
- [BZOJ]4448: [Scoi2015]情报传递 主席树+LCA
- bzoj 4448: [Scoi2015]情报传递 可持久化线段树+离线
- 三十秒的小习惯,一辈子的大影响
- 免费编程书籍-中文版
- CUDA8.0安装配置 for VS2013
- 『ORACLE』父子游标(11g)--未完
- Linux学习笔记
- bzoj4448 [Scoi2015]情报传递 树链剖分+树状数组
- java NIO系列教程(七)
- UML一篇文章就学通!
- struts2学习1 笔记
- webView拦截超链接
- Android 热更新 tinker 在Android 简单的使用 (替换class)
- Java:单例模式的七种写法
- 面试题9:题目二青蛙跳台阶
- Golang存取更新时间(time.Time)