【BZOJ1483】【codevs2335】&&【hdu5997】梦幻布丁+加强版,LCA+主席树
2016-12-23 10:32
239 查看
传送门1
传送门2
传送门3
思路:
这还要从上一周的BC说起……
因为正好放大周,在家里颓了一天后准备BC#90
干完两个签到题以后开始搞T3
抽象了很久YY出来一个并查集+主席树
连蒙带骗写了一发交上去WA了,发现想法有漏洞然后就弃疗了
赛后得知是梦幻布丁的加强版
无限仰慕zky学长一血T3
之后的几天一直在发低烧,没去上学,断断续续又想了想之前的做法,发现是可做的,只要把并查集改成LCA就可以了
我们可以把序列中相邻的两个元素看成一个点对,每个点对有一个终止时间,过了这个终止时间这个点对就是同种颜色的了(即不再对答案做出贡献),每一次的修改实际上是把当前时间加1,每次统计答案实际上是统计区间内终止时间大于等于当前时间的点对数,这显然是主席树做的问题了
现在我们来考虑如何确定每个点对的终止时间
类似于kruskal生成树一样的想法,用LCA来搞
记录每一个真实颜色下的点,然后每次修改相当于把两坨点合到一起,下面再挂一个新点,表示它们合并时的时间
相当于是一个二叉树的森林
每个点对的终止时间就是两个点的LCA所代表的合并时间
(如果它们不属于同一棵树的话,就把终止时间当成+∞就可以了)
复杂度是O(nlogn)
颜色数略多,要先离散化一下
用倍增+主席树的话感觉内存稍稍有点卡,所以在写加强版的时候把倍增改成了链剖
如果有机会的话可能再补一个链表+启发式合并的做法不过网上好像都是启发式合并+链表的做法吧
梦幻布丁-倍增LCA:
加强版-链剖LCA+主席树:
传送门2
传送门3
思路:
这还要从上一周的BC说起……
因为正好放大周,在家里颓了一天后准备BC#90
干完两个签到题以后开始搞T3
抽象了很久YY出来一个并查集+主席树
连蒙带骗写了一发交上去WA了,发现想法有漏洞然后就弃疗了
赛后得知是梦幻布丁的加强版
无限仰慕zky学长一血T3
之后的几天一直在发低烧,没去上学,断断续续又想了想之前的做法,发现是可做的,只要把并查集改成LCA就可以了
我们可以把序列中相邻的两个元素看成一个点对,每个点对有一个终止时间,过了这个终止时间这个点对就是同种颜色的了(即不再对答案做出贡献),每一次的修改实际上是把当前时间加1,每次统计答案实际上是统计区间内终止时间大于等于当前时间的点对数,这显然是主席树做的问题了
现在我们来考虑如何确定每个点对的终止时间
类似于kruskal生成树一样的想法,用LCA来搞
记录每一个真实颜色下的点,然后每次修改相当于把两坨点合到一起,下面再挂一个新点,表示它们合并时的时间
相当于是一个二叉树的森林
每个点对的终止时间就是两个点的LCA所代表的合并时间
(如果它们不属于同一棵树的话,就把终止时间当成+∞就可以了)
复杂度是O(nlogn)
颜色数略多,要先离散化一下
用倍增+主席树的话感觉内存稍稍有点卡,所以在写加强版的时候把倍增改成了链剖
如果有机会的话可能再补一个链表+启发式合并的做法不过网上好像都是启发式合并+链表的做法吧
梦幻布丁-倍增LCA:
#include<cstdio> #include<iostream> #include<algorithm> #define M 100003 using namespace std; int n,m,cnt; int a[M],b[M*3],col[1000005],belong[M*3],fa[M<<2][19],son[M<<2][2],dep[M<<2],sum[M]; struct os{ int tp,x,y; bool ok; }q[M]; void dfs(int x) { for (int i=1;1<<i<=dep[x];++i) fa[x][i]=fa[fa[x][i-1]][i-1]; if (son[x][0]) fa[son[x][0]][0]=x,dep[son[x][0]]=dep[x]+1,dfs(son[x][0]); if (son[x][1]) fa[son[x][1]][0]=x,dep[son[x][1]]=dep[x]+1,dfs(son[x][1]); } int LCA(int x,int y) { if (dep[x]<dep[y]) swap(x,y); for (int i=18;i>=0;--i) if (fa[x][i]&&dep[fa[x][i]]>=dep[y]) x=fa[x][i]; if (x==y) return x; for (int i=18;i>=0;--i) if (fa[x][i]&&fa[y][i]&&fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i]; if (fa[x][0]==fa[y][0]) return fa[x][0]; else return 0; } main() { scanf("%d%d",&n,&m); for (int i=1;i<=n;++i) scanf("%d",a+i), b[++b[0]]=a[i]; for (int i=1;i<=m;++i) { scanf("%d",&q[i].tp); if (q[i].tp==1) scanf("%d%d",&q[i].x,&q[i].y), b[++b[0]]=q[i].x,b[++b[0]]=q[i].y; } sort(b+1,b+b[0]+1); b[0]=unique(b+1,b+b[0]+1)-b-1; for (int i=1;i<=b[0];++i) belong[i]=col[b[i]]=i; cnt=b[0]; for (int i=1;i<=m;++i) if (q[i].tp==1) { int x=col[q[i].x],y=col[q[i].y]; if (x==y) continue; if (!belong[x]) continue; if (!belong[y]) belong[y]=belong[x], belong[x]=0; else q[i].ok=1, son[++cnt][0]=belong[x], son[cnt][1]=belong[y], belong[x]=0, belong[y]=cnt; } for (int i=1;i<=b[0];++i) if (belong[i]) dfs(belong[i]); for (int t,i=2;i<=n;++i) { t=LCA(col[a[i]],col[a[i-1]]); if (!t) ++sum[cnt+1-b[0]]; else if (t>b[0]) ++sum[t-b[0]]; } for (int i=1;i<=cnt+1-b[0];++i) sum[i]+=sum[i-1]; for (int t=0,i=1;i<=m;++i) if (q[i].tp==1) t+=q[i].ok; else printf("%d\n",sum[cnt+1-b[0]]-sum[t]+1); }
加强版-链剖LCA+主席树:
#include<cstdio> #include<iostream> #include<algorithm> #include<cstring> #define M 100003 #define ls(x) ch[x][0] #define rs(x) ch[x][1] using namespace std; int n,m,cnt; int a[M],b[M*3],col[1000005],belong[M*3],fa[M<<2],top[M<<2],siz[M<<2],wt[M<<2],son[M<<2][2],dep[M<<2]; struct os{ int tp,x,y; bool ok; }q[M]; int tot,root[M],ch[M*17][2],sum[M*17]; void build(int rt,int L,int R,int now,int val) { sum[now]=sum[rt]+1; if (L==R) return ; int mid=(L+R)>>1; if (mid>=val) rs(now)=rs(rt), ls(now)=++tot, build(ls(rt),L,mid,ls(now),val); else ls(now)=ls(rt), rs(now)=++tot, build(rs(rt),mid+1,R,rs(now),val); } int get(int begin,int end,int L,int R,int val) { if (begin==end) if (end>=val) return sum[R]-sum[L]; else return 0; int mid=(begin+end)>>1; if (mid>=val) return sum[rs(R)]-sum[rs(L)]+get(begin,mid,ls(L),ls(R),val); else return get(mid+1,end,rs(L),rs(R),val); } void dfs(int x) { siz[x]=1; if (!son[x][0]&&!son[x][1]) return; fa[son[x][0]]=x; dep[son[x][0]]=dep[x]+1; dfs(son[x][0]); siz[x]+=siz[son[x][0]]; fa[son[x][1]]=x; dep[son[x][1]]=dep[x]+1; dfs(son[x][1]); siz[x]+=siz[son[x][1]]; if (siz[son[x][1]]>siz[son[x][0]]) wt[x]=son[x][1]; else wt[x]=son[x][0]; } void dfs2(int x,int tp) { top[x]=tp; if (!wt[x]) return; dfs2(wt[x],tp); if (wt[x]==son[x][0]) dfs2(son[x][1],son[x][1]); else dfs2(son[x][0],son[x][0]); } int LCA(int x,int y) { for (;x&&y&&top[x]!=top[y];x=fa[top[x]]) if (dep[top[x]]<dep[top[y]]) swap(x,y); if (!x||!y) return 0; return dep[x]>dep[y]?y:x; } void work() { b[0]=0;tot=0; memset(son,0,sizeof(son)); memset(fa,0,sizeof(fa)); memset(siz,0,sizeof(siz)); memset(wt,0,sizeof(wt)); scanf("%d%d",&n,&m); for (int i=1;i<=n;++i) scanf("%d",a+i), b[++b[0]]=a[i]; for (int i=1;i<=m;++i) { scanf("%d%d%d",&q[i].tp,&q[i].x,&q[i].y); if (q[i].tp==1) b[++b[0]]=q[i].x,b[++b[0]]=q[i].y; } sort(b+1,b+b[0]+1); b[0]=unique(b+1,b+b[0]+1)-b-1; for (int i=1;i<=b[0];++i) belong[i]=col[b[i]]=i; cnt=b[0]; for (int i=1;i<=m;++i) if (q[i].tp==1) { q[i].ok=0; int x=col[q[i].x],y=col[q[i].y]; if (x==y) continue; if (!belong[x]) continue; if (!belong[y]) belong[y]=belong[x], belong[x]=0; else q[i].ok=1, son[++cnt][0]=belong[x], son[cnt][1]=belong[y], belong[x]=0, belong[y]=cnt; } for (int i=1;i<=b[0];++i) if (belong[i]) dfs(belong[i]), dfs2(belong[i],belong[i]); root[1]=++tot; for (int t,i=2;i<=n;++i) { t=LCA(col[a[i]],col[a[i-1]]); if (!t) root[i]=++tot,build(root[i-1],1,cnt+1-b[0],root[i],cnt+1-b[0]); else if (t>b[0]) root[i]=++tot,build(root[i-1],1,cnt+1-b[0],root[i],t-b[0]); else root[i]=root[i-1]; } for (int t=0,i=1;i<=m;++i) if (q[i].tp==1) t+=q[i].ok; else printf("%d\n",get(1,cnt+1-b[0],root[q[i].x],root[q[i].y],t+1)+1); } main() { int T; for (scanf("%d",&T);T;--T) work(); }
相关文章推荐
- BZOJ_P2190&&Codevs_P2296 [SDOI2008]仪仗队(欧拉函数线性筛)
- bzoj 4539: [Hnoi2016]树 主席树&lca
- [LCT && 主席树] BZOJ3514 .Codechef MARCH14 GERALD07 加强版
- BZOJ 3673: 可持久化并查集 by zky&&3674: 可持久化并查集加强版|主席树
- 【数据结构】CODE[VS] 2491 && bzoj 3039玉蟾宫 (单调栈)
- [bzoj3545+3551][ONTAK2010]Peaks&&加强版(离线+线段树合并)||(kruskal重构树&&dfs序+主席树)
- bzoj 3545&&3551: [ONTAK2010]Peaks &&加强版 平衡树&&并查集合并树&&主席树
- bzoj3514 Codechef MARCH14 GERALD07加强版 LCT&&主席树
- 【NOI2009】Bzoj1562 & Codevs1843 变换序列
- BZOJ_1208_&_Codevs_1258_[HNOI2004]_宠物收养所_(平衡树/set)
- bzoj3674 可持久化并查集加强版 (主席树 & 并查集)
- bzoj1040&CodeVS1423 骑士
- 【BZOJ-3545&3551】Peaks&加强版 Kruskal重构树 + 主席树 + DFS序 + 倍增
- [主席树 Kruscal] BZOJ 3545 [ONTAK2010]Peaks & 3551 [ONTAK2010]Peaks加强版
- [BZOJ4408&&BZOJ4299][FJOI2016 && Codechef]神秘数&&FRBSUM(主席树)
- bzoj 1050: [HAOI2006]旅行comf&&【codevs1001】
- bzoj1499: [NOI2005]瑰丽华尔兹&&codevs1748 单调队列优化dp
- BZOJ_1588_&_Codevs_1296_[HNOI2002]_营业额统计(平衡树/set)
- BZOJ_1798_&_Codevs_2216_[AHOI_2009]_行星序列_(线段树)
- BZOJ_P2729[HNOI2012]排队&Codevs_P1994 排队(数论)