[UER #1C]Dzy Loves Graph
2016-07-03 08:26
411 查看
题目大意
有n个结点,初始没有边。m个操作,操作类型有三:1、a与b之间连一条长度为i的边(i为操作编号)
2、删除比边权最大的k条边。
3、撤销刚刚执行的操作,保证撤销的不是撤销操作。
每次操作后输出最小生成树所有边权和。
可持久化并查集
有许多版本,于是我们发现版本之间形成树的结构,为什么?加入的边越来越大,因此删除操作相当于跳到k级祖先,每次添加操作就在下面加一个儿子,所以是树的结构。
撤销也很容易,直接看i-2所在版本即可。
我们维护并查集,如果加入的边的两端点在同一集合,由于是最小生成树,而新加入这边一定边权最大,所以不需要更新答案。
于是我们可以维护可持久化并查集。
至于跳到祖先,可以每加入一个点就处理一下倍增数组。
程序其实是非AC代码QAQ
#include<cstdio> #include<algorithm> #include<cmath> #define fo(i,a,b) for(i=a;i<=b;i++) using namespace std; const int maxn=300000+10,maxm=500000+10; int fa[maxm][25],last[maxm],data[maxm],cnt[maxm],wz[maxm]; int left[maxm*6],right[maxm*6],key[maxm*6],root[maxm]; int i,j,k,l,t,n,m,tot,top,now; char ch; int read(){ int x=0,f=1; char ch=getchar(); while (ch<'0'||ch>'9'){ if (ch=='-') f=-1; ch=getchar(); } while (ch>='0'&&ch<='9'){ x=x*10+ch-'0'; ch=getchar(); } return x*f; } char get(){ char ch=getchar(); while (ch!='A'&&ch!='D'&&ch!='R') ch=getchar(); return ch; } int newnode(int x){ top++; left[top]=left[x]; right[top]=right[x]; key[top]=key[x]; return top; } void change(int &x,int l,int r,int a,int b){ x=newnode(x); if (l==r){ key[x]=b; return; } int mid=(l+r)/2; if (a<=mid) change(left[x],l,mid,a,b);else change(right[x],mid+1,r,a,b); } int query(int x,int l,int r,int a){ if (l==r) return key[x]; int mid=(l+r)/2; if (a<=mid) return query(left[x],l,mid,a);else return query(right[x],mid+1,r,a); } int getfa(int id,int x){ int f=query(root[id],1,n,x); if (f==0) return x; f=getfa(id,f); change(root[id],1,n,x,f); return f; } int getfather(int x,int y){ int j=floor(log(m)/log(2)); while (j>=0){ if ((1<<j)<=y){ y-=(1<<j); x=fa[x][j]; } j--; } return x; } int main(){ freopen("dzy.in","r",stdin); n=read();m=read(); fo(i,1,m){ ch=get(); if (ch=='A'){ ++tot; fa[tot][0]=now; data[tot]=data[now]; cnt[tot]=cnt[now]; root[tot]=root[now]; now=tot; fo(j,1,floor(log(m)/log(2))) fa[tot][j]=fa[fa[tot][j-1]][j-1]; j=read();k=read(); j=getfa(tot,j); k=getfa(tot,k); if (j!=k){ change(root[tot],1,n,j,k); data[tot]+=i; cnt[tot]++; } } else if (ch=='D'){ k=read(); now=getfather(now,k); } else if (ch=='R') now=wz[i-2]; if (cnt[now]==n-1) printf("%d\n",data[now]);else printf("0\n"); wz[i]=now; } }
相关文章推荐
- [leetcode] 334. Increasing Triplet Subsequence
- ECIR 2016 Paper Modelling User Interest for Zero-query Ranking
- 687C: The values you can make
- Invalidate(TRUE)与Invalidate(FALSE)区别(前者会发送WM_ERASEBKGND消息全部刷新,然后使用WM_PAINT消息绘制,而后者只发送WM_PAINT消息)
- iOS开发之Socket通信实战--Request请求数据包编码模块
- P6 EPPM Installation and Configuration Guide 16 R1 April 2016
- requireJs 初探
- Java集合框架(下)之Map的containsKey()与containsValue()方法
- JNI/NDK develop guide(2) How JVM find native method
- 【UOJ #210】【UER #6】寻找罪犯 (2-SAT)
- 【UOJ #209】【UER #6】票数统计
- @RequestParam的作用
- PAT (Advanced Level) 1085. Perfect Sequence (25)
- iOS GPUImage之GPUImageMovie视频滤镜(1)
- 进程序名得到进程ID和句柄与进程的公司名(使用快照和GetPeFileCompany和VerQueryValueW等函数)
- ArrayDeque源码解析
- STL之优先级队列priority_queue
- WindowsBuilder控件中文编码问题
- PAT - 甲级 - 1007. Maximum Subsequence Sum (25)
- iOS开发~一个UIButton的小问题一定要小心