2809: [Apio2012]dispatching 启发式合并treap 可并堆
2016-02-21 09:05
369 查看
我曾写过N次启发式合并splay。。由于太弱从来没调出来过。。
这次写了一发treap终于过啦!(然而常数太大被可并堆虐成狗了)
首先,作法显然,从底向上,每次计算子树的前k小数保证和<=M,然后将两棵子树合并,更新答案。
显然treap和可并堆都是支持这些操作的。不过treap合并的时候有很多无效的节点一直在合并,如果能split的话应该能快一些吧(然而我不会)。
treap:
可并堆:
这次写了一发treap终于过啦!(然而常数太大被可并堆虐成狗了)
首先,作法显然,从底向上,每次计算子树的前k小数保证和<=M,然后将两棵子树合并,更新答案。
显然treap和可并堆都是支持这些操作的。不过treap合并的时候有很多无效的节点一直在合并,如果能split的话应该能快一些吧(然而我不会)。
treap:
#include<iostream> #include<cstdio> #include<cstdlib> #define N 100005 #define ll long long using namespace std; int n,cnt,tmp; ll ans,M; int next[N<<1],list[N<<1]; int head ,f ,size ,root ,rnd ,ls ,rs ; ll sum ,val ,c ,l ; inline ll read() { ll a=0,f=1; char c=getchar(); while (c<'0'||c>'9') {if (c=='-') f=-1; c=getchar();} while (c>='0'&&c<='9') {a=a*10+c-'0'; c=getchar();} return a*f; } inline void addedge(int x,int y) { next[++cnt]=head[x]; head[x]=cnt; list[cnt]=y; } int find(int i) { return f[i]==i?i:f[i]=find(f[i]); } inline void pushup(int k) { size[k]=size[ls[k]]+size[rs[k]]+1; sum[k]=sum[ls[k]]+sum[rs[k]]+val[k]; } inline void lturn(int &k) { int t=rs[k]; rs[k]=ls[t]; ls[t]=k; pushup(k); pushup(t); k=t; } inline void rturn(int &k) { int t=ls[k]; ls[k]=rs[t]; rs[t]=k; pushup(k); pushup(t); k=t; } void insert(int &k,ll x,int y) { if (!k) { k=y; size[k]=1; sum[k]=x; val[k]=x; rnd[k]=rand(); return; } size[k]++; sum[k]+=x; if (x<=val[k]) { insert(ls[k],x,y); if (rnd[ls[k]]>rnd[k]) rturn(k); } else { insert(rs[k],x,y); if (rnd[rs[k]]>rnd[k]) lturn(k); } } void merge(int x,int &y) { if (!x) return; merge(ls[x],y); merge(rs[x],y); ls[x]=rs[x]=0; insert(y,c[x],x); } void find_max(int k,ll MAXN) { if (!k) return; if (sum[ls[k]]+val[k]<=MAXN) tmp+=size[ls[k]]+1,find_max(rs[k],MAXN-sum[ls[k]]-val[k]); else if (sum[ls[k]]<=MAXN) {tmp+=size[ls[k]]; return;} else find_max(ls[k],MAXN); } void dfs(int x) { if (!head[x]) {ans=max(ans,l[x]); return;} for (int i=head[x];i;i=next[i]) dfs(list[i]); for (int i=head[x];i;i=next[i]) { int p=find(x),q=find(list[i]); if (size[root[p]]>size[root[q]]) swap(p,q); merge(root[p],root[q]); f[p]=q; } int p=find(x); tmp=0; find_max(root[p],M); ans=max(ans,tmp*l[x]); } int main() { n=read(); M=read(); for (int i=1;i<=n;i++) f[i]=i; for (int i=1;i<=n;i++) { int x=read(); c[i]=read(); l[i]=read(); if (x) addedge(x,i); insert(root[i],c[i],i); } dfs(1); cout << ans << endl; return 0; }
可并堆:
#include<iostream> #include<cstdio> #include<cstdlib> #define N 100005 #define ll long long using namespace std; int n,cnt; ll M,ans; ll l ,c ,sum ; int ls ,rs ,d ,root ,head ,next ,list ,size ; inline ll read() { ll a=0,f=1; char c=getchar(); while (c<'0'||c>'9') {if (c=='-') f=-1; c=getchar();} while (c>='0'&&c<='9') {a=a*10+c-'0'; c=getchar();} return a*f; } inline void insert(int x,int y) { next[++cnt]=head[x]; head[x]=cnt; list[cnt]=y; } int merge(int x,int y) { if (!x||!y) return x+y; if (c[x]<c[y]) swap(x,y); sum[x]+=sum[y]; size[x]+=size[y]; rs[x]=merge(rs[x],y); if (d[rs[x]]>d[ls[x]]) swap(ls[x],rs[x]); d[x]=d[rs[x]]+1; return x; } int main() { n=read(); M=read(); for (int i=1;i<=n;i++) { int x=read(); c[i]=read(); l[i]=read(); if (x) insert(x,i); root[i]=i; sum[i]=c[i]; size[i]=1; } for (int x=n;x;x--) { for (int i=head[x];i;i=next[i]) root[x]=merge(root[x],root[list[i]]); while (sum[root[x]]>M) root[x]=merge(ls[root[x]],rs[root[x]]); ans=max(ans,size[root[x]]*l[x]); } cout << ans << endl; return 0; }
相关文章推荐
- LeetCode Number of Islands II
- 扫描文件夹获取包含子文件夹在内的所有文件
- String使用字面值常量赋值与new String()赋值的区别
- NEC 框架规范 css function
- LeetCode Roman to Integer
- jqMobi(App Framework)入门学习(一)
- codeforces 629D. Babaei and Birthday Cake
- bit-map牛刀小试:数组test[X]的值所有在区间[1, 8000]中, 现要输出test中反复的数。要求:1. 不能改变原数组; 2.时间复杂度为O(X);3.除test外空间不超过1KB
- 全面详细的jQuery常见开发技巧手册
- Hive Operators and User-Defined Functions (UDFs)
- php课程---建立一个简单的下拉列表框
- Android 开源项目android-open-project解析之(三) ScrollView,TimeView,TipView,FlipView
- php课程---初学练习
- 完善的jquery处理机制
- php课程---JavaScript改变HTML中的元素
- html5 isPointInPath相关操作
- 从头開始写项目Makefile(七):统一目标输出文件夹
- 使用工具来提升Android开发效率
- [LeetCode 329] Longest Increasing Path in a Matrix
- Android读取assets中的文件