BZOJ 3545: [ONTAK2010]Peaks|Splay启发式合并
2016-02-24 17:13
483 查看
其实启发式合并就是暴力合并,然后就是名字比较高端
暴力合并的时候把小的往大的合并,这样可以保证复杂度不会闹鬼
先说这题的做法,把边从小到大排序,把询问按对边的限制也从小到大排序,然后枚举询问,动态加满足小于等于当前限制的边,暴力合并。
做法很简单,然后就很奇怪一直TLE..非常玄学..然后通过某种奇怪的方式发现了bug:
在暴力合并的时候,我们需要dfs遍历整个较小的splay树,把所有的节点都加入较大的那个splay中,然后如果是我们先加入当前的点,后遍历左右子树,就会TLE,如果先遍历左右子树后加入这个节点就会快的飞起……
23333求神犇解释
暴力合并的时候把小的往大的合并,这样可以保证复杂度不会闹鬼
先说这题的做法,把边从小到大排序,把询问按对边的限制也从小到大排序,然后枚举询问,动态加满足小于等于当前限制的边,暴力合并。
做法很简单,然后就很奇怪一直TLE..非常玄学..然后通过某种奇怪的方式发现了bug:
在暴力合并的时候,我们需要dfs遍历整个较小的splay树,把所有的节点都加入较大的那个splay中,然后如果是我们先加入当前的点,后遍历左右子树,就会TLE,如果先遍历左右子树后加入这个节点就会快的飞起……
23333求神犇解释
#include<cstdio> #include<cstdlib> #include<cstring> #include<cmath> #include<queue> #include<vector> #include<set> #include<map> #include<algorithm> #include<iostream> #define N 520050 #define e exp(1.0) #define pi acos(-1.0) using namespace std; int sc() { int i=0,f=1; char c=getchar(); while(c>'9'||c<'0'){if(c=='-')f=-1;c=getchar();} while(c>='0'&&c<='9')i=i*10+c-'0',c=getchar(); return i*f; } struct W{int x,y,z;}a ; struct Q{int v,x,k,p;}b ; int v ,ans ,root ,FA ; int fa[N*10],ch[N*10][2],w[N*10],s[N*10]; int n,m,q,cnt; bool cmp1(W a,W b){return a.z<b.z;} bool cmp2(Q a,Q b){return a.x<b.x;} int find(int x) { return FA[x]==x?x:FA[x]=find(FA[x]); } int son(int x){return ch[fa[x]][1]==x;} void push_up(int x){s[x]=s[ch[x][0]]+s[ch[x][1]]+1;} void rotate(int x,int &f) { int y=fa[x],z=fa[y],b=son(x),c=son(y); ch[z][c]=x; fa[x]=z; ch[y][b]=ch[x][!b]; if(ch[x][!b])fa[ch[x][!b]]=y; ch[x][!b]=y; fa[y]=x; push_up(y),push_up(x); if(y==f) f=x; } void splay(int x,int &f) { while(x!=f) { int y=fa[x],z=fa[y]; if(y==f) rotate(x,f); else { if(ch[z][0]==y^ch[y][0]==x) rotate(x,f); else rotate(y,f); rotate(x,f); } } } void add(int &x,int k,int f,int c) { if(!x) { x=++cnt; s[x]=1; w[x]=k; fa[x]=f; splay(x,root[c]); return; } s[x]++; if(v[k]<v[w[x]])add(ch[x][0],k,x,c); else add(ch[x][1],k,x,c); } void insert(int x,int f) { if(!x)return; insert(ch[x][0],f); insert(ch[x][1],f); add(root[f],w[x],0,f); /* TLE的写法!!! add(root[f],w[x],0,f); insert(ch[x][0],f); insert(ch[x][1],f); */ } void merge(int x,int y) { if(s[root[x]]<s[root[y]])swap(x,y); FA[y]=x; insert(root[y],x); } int search(int x,int k) { if(s[x]<k)return -1; if(k==s[ch[x][1]]+1)return v[w[x]]; else if(k<=s[ch[x][1]]) return search(ch[x][1],k); else return search(ch[x][0],k-s[ch[x][1]]-1); } int main() { n=sc(),m=sc(),q=sc();cnt=n; for(int i=1;i<=n;i++)v[i]=sc(),FA[i]=root[i]=w[i]=i,s[i]=1; for(int i=1;i<=m;i++) a[i].x=sc(),a[i].y=sc(),a[i].z=sc(); for(int i=1;i<=q;i++) b[i].v=sc(),b[i].x=sc(),b[i].k=sc(),b[i].p=i; sort(a+1,a+m+1,cmp1); sort(b+1,b+q+1,cmp2); int L=1; for(int i=1;i<=q;i++) { int mn=b[i].x; while(a[L].z<=mn&&L<=m) { int fx=find(a[L].x),fy=find(a[L].y); if(fx!=fy) merge(fx,fy); L++; } int fx=find(b[i].v); ans[b[i].p]=search(root[fx],b[i].k); } for(int i=1;i<=q;i++)printf("%d\n",ans[i]); return 0; }
相关文章推荐
- java string 反转
- 在jsp中解决div的scroll浮动不匹配的情况
- 让div左右对齐自适应高度的网页特效(常看)
- 自己动手做一个--手势解锁
- 交叉销售功能介绍-功能
- Python语言特性(二)
- Berland National Library(模拟题目)
- Netty-私有协议栈
- 工作流入门链接
- 关于登录退出后的再次登录页面保存的问题
- 必须包含“数字”,“字母”,“特殊字符” 两种以上的正在表达式!
- Gentoo/Arch常用软件配置
- Nmon命令行:Linux系统性能的监测利器
- JQuery给textarea取值和赋值
- iOS开发~CocoaPods使用
- 汉诺塔与递归之C++ 和Python实现
- C#访问openfire服务器之一:服务端的安装、客户端的简介
- 关于强引用和弱引用
- 403
- 大城市的房子