[BZOJ4551][JZOJ4604]【TJOI&HEOI2016】D1T1 树
来源:互联网 发布:ubuntu怎么连接wifi 编辑:程序博客网 时间:2024/05/16 08:03
Description
在2016年,佳媛姐姐刚刚学习了树,非常开心。
现在他想解决这样一个问题:
给定一颗有根树(根为1),有以下两种操作:
1. 标记操作:对某个结点打上标记(在最开始,只有结点1有标记,其他结点均无标记,而且对于某个结点,可以打多次标记。)
2. 询问操作:询问某个结点最近的一个打了标记的祖先(这个结点本身也算自己的祖
先)你能帮帮他吗?
Solution
这题至少有两种解法。
- 解法1:可以离线处理。把每个操作读入后倒序,就变成了删除节点,也就是合并联通块。这样完全可以用并查集完成。
- 解法2:如果一定要在线的话。可以用树链剖分,每个询问就是要求
1 ~x 的路径上最深的有标记的点。显然这里DFS序越大深度越大。修改就是把这个点改成它的DFS序,线段树维护最大值即可。
解法1的复杂度是
解法2的复杂度是
然而比赛的时候,本人对自己的代码能力十分自信,机(sha)智(bi)的打了解法2。 结果一直拍到11:00
Code
下面是比赛时候打的链剖~
#include<cstdio>#include<cstdlib>#include<cmath>#include<cstring>#include<algorithm>#include<iostream>#define fo(i,a,b) for(i=a;i<=b;i++)#define fod(i,a,b) for(i=a;i>=b;i--)#define MAXN 100005using namespace std;struct note{ int mx,ls,rs; }tree[2000005];struct rd{ int x,y;}a[MAXN];int top[MAXN],size[MAXN],son[MAXN],dfn[MAXN],pt[MAXN],ft[MAXN],deep[MAXN],n,m,a1[MAXN][2],df,num;bool cmp(rd x,rd y){ return x.x<y.x;}void dfs1(int k){ int i,mx=0; if (a1[k][0]!=0) fo(i,a1[k][0],a1[k][1]) { dfs1(a[i].y); size[k]+=size[a[i].y]; if (size[a[i].y]>mx) { son[k]=a[i].y; mx=size[a[i].y]; } } size[k]++;}void dfs2(int k){ int i; dfn[k]=++df; pt[df]=k; if (son[k]!=0) { top[son[k]]=top[k]; dfs2(son[k]); } if (a1[k][0]!=0) fo(i,a1[k][0],a1[k][1]) { if(a[i].y==son[k]) continue; top[a[i].y]=a[i].y; dfs2(a[i].y); }}int find(int now,int l,int r,int x,int y){ if (now==0) return 0; int ls=tree[now].ls,rs=tree[now].rs; if (l==x&&r==y) return tree[now].mx; int mid=(l+r)/2; if (y<=mid) return find(ls,l,mid,x,y); else if(x>mid) return find(rs,mid+1,r,x,y); else return max(find(ls,l,mid,x,mid),find(rs,mid+1,r,mid+1,y));}void change(int now,int l,int r,int x,int y,int v){ int ls=tree[now].ls,rs=tree[now].rs; if (l==x&&r==y) { tree[now].mx=v; return; } int mid=(l+r)/2; if (ls==0) ls=tree[now].ls=++num,tree[ls].mx=0; if (rs==0) rs=tree[now].rs=++num,tree[rs].mx=0; if (y<=mid) change(ls,l,mid,x,y,v); else if(x>=mid) change(rs,mid+1,r,x,y,v); else change(ls,l,mid,x,mid,v),change(rs,mid+1,r,mid+1,y,v); tree[now].mx=max(tree[ls].mx,tree[rs].mx);}int ask(int x,int y){ int fx=top[x],fy=top[y]; if (fx==fy) { if (deep[x]>deep[y]) swap(x,y); return find(1,1,n,dfn[x],dfn[y]); } else { if (deep[fx]<deep[fy]) swap(fx,fy),swap(x,y); return max(find(1,1,n,dfn[fx],dfn[x]),ask(ft[fx],y)); }}int main(){ cin>>n>>m; int i,j,k; deep[1]=1; memset(size,0,sizeof(size)); df=0; fo(i,1,n-1) { int x,y; scanf("%d%d",&x,&y); ft[y]=x; deep[y]=deep[x]+1; a[i].x=x; a[i].y=y; } sort(a+1,a+n,cmp); fo(i,1,n-1) { if (a[i].x!=a[i-1].x) { a1[a[i].x][0]=i; a1[a[i-1].x][1]=i-1; } } a1[a[n-1].x][1]=n-1; top[1]=1; dfs1(1); dfs2(1); num=1; change(1,1,n,1,1,1); int pq=0; fo(i,1,m) { char ch; scanf("\n"); scanf("%c%d",&ch,&k); if (ch=='Q') printf("%d\n",pt[ask(1,k)]); else change(1,1,n,dfn[k],dfn[k],dfn[k]); } }
0 0
- [BZOJ4551][JZOJ4604]【TJOI&HEOI2016】D1T1 树
- [bzoj4551][TJOI&HEOI2016]树
- BZOJ4551 [Tjoi2016&Heoi2016]树
- 【bzoj4551】[Tjoi2016&Heoi2016]树
- bzoj4551【TJOI2016&HEOI2016】树
- BZOJ4551: [Tjoi2016&Heoi2016]树
- bzoj4551: [Tjoi2016&Heoi2016]树
- BZOJ4551[HEOI2016]树
- 【bzoj4551】[Tjoi2016&Heoi2016]树
- 【bzoj4551】【Tjoi2016】【Heoi2016】【树】【线段树】
- 【bzoj4551】【Tjoi2016&Heoi2016】【树】【并查集】
- BZOJ4551——[Tjoi2016&Heoi2016]树
- Jzoj4604 树
- [BZOJ4551][Tjoi2016&Heoi2016]树 dfs序+线段树
- [BZOJ4551][Tjoi2016&Heoi2016]树(dfs序+线段树)
- [bzoj4551][Tjoi2016&Heoi2016]树 dfs序+线段树
- 【bzoj4551】[Tjoi2016&Heoi2016]树 暴力?树剖+树状数组+二分
- 倍增+树状数组——BZOJ4551 [Tjoi2016&Heoi2016]树
- oninput,onpropertychange,onchange的用法
- android studio Git版本管理工具的使用
- Java ConcurrentModificationException异常原因和解决方法
- web,视频播放两种方法
- 关于语义化标签
- [BZOJ4551][JZOJ4604]【TJOI&HEOI2016】D1T1 树
- Unsupported major.minor version 52.0那点坑
- 关于如何引入GPUImage到自己的项目中
- Java并发编程:并发容器之ConcurrentHashMap(转载)
- Putty打不开
- Cannot resolve the import org. Cocos2dx. Lib 错误解决方法
- mac 安装brew
- Nexus 7 搞机教程
- 显示服务器上传的文件