bzoj 2809 dispatching

一开始没想出来,想大概需要维护一下工资单调递增然后求和什么的,后来一查发现是splay启发式合并,于是我赶紧先去做了一下Neverland那个题,发下什么启发式合并其实就是暴力合并......表示无奈。

这个题居然这么轻松就写过了,而且还是1A,代码居然比Neverland还短......就是维护一下sum工资和就行了,查找的话类比寻找第k小的数。

dispatching
  1 #include<iostream>
  2 #include<cstdio>
  3 #include<algorithm>
  4 #include<cstring>
  5 #include<cmath>
  6 #define maxn 200000
  7 using namespace std;
  8 
  9 int c[maxn][2];
 10 int t[maxn],fir[maxn],next[maxn],fa[maxn],key[maxn],size[maxn],q[maxn];
 11 long long sum[maxn],able[maxn];
 12 int n,m,tot,root;
 13 long long ans;
 14 
 15 inline void update(int x)
 16 {
 17         if (!x) return;
 18         size[x]=size[c[x][0]]+size[c[x][1]]+1;
 19         sum[x]=sum[c[x][0]]+sum[c[x][1]]+key[x];
 20 }
 21 
 22 inline void rotate(int x)
 23 {
 24         int y=fa[x],z=fa[y];
 25         int p=(c[y][1]==x),q=p^1;
 26         if (fa[y])
 27                 if (c[z][0]==y) c[z][0]=x; else c[z][1]=x;
 28         fa[x]=z; fa[y]=x; fa[c[x][q]]=y;
 29         c[y][p]=c[x][q]; c[x][q]=y;
 30         update(y);
 31 }
 32 
 33 inline void splay(int x)
 34 {
 35         while (fa[x])
 36         {
 37                 int y=fa[x],z=fa[y];
 38                 if (fa[y])
 39                         if ((c[z][0]==y)xor(c[y][0]==x)) rotate(x); else rotate(y);
 40                 rotate(x);
 41         }
 42         update(x);
 43 }
 44 
 45 inline void insert(int &t,int anc,int x)
 46 {
 47         if (!t)
 48         {
 49                 t=x;
 50                 fa[x]=anc;
 51                 splay(x);
 52                 return;
 53         }
 54         if (key[x]<=key[t]) insert(c[t][0],t,x);
 55         else insert(c[t][1],t,x);
 56 }
 57 
 58 inline void merge(int x,int y)
 59 {
 60         if (size[x]>size[y]) swap(x,y);
 61         splay(x); splay(y);
 62         int head=0, tail=1;
 63         q[0]=y; q[1]=x;
 64         while (head<tail)
 65         {
 66                 int now=q[++head];
 67                 if (c[now][0]) q[++tail]=c[now][0];
 68                 if (c[now][1]) q[++tail]=c[now][1];
 69                 c[now][0]=c[now][1]=0;
 70                 insert(q[head-1],0,now);
 71         }
 72 }
 73 
 74 inline long long find(int t,int k)
 75 {
 76         if (!t) return 0;
 77         if (k==sum[c[t][0]]+key[t]) return size[c[t][0]]+1;
 78         if (k<sum[c[t][0]]+key[t]) return find(c[t][0],k);
 79         if (k>sum[c[t][0]]+key[t]) return find(c[t][1],k-sum[c[t][0]]-key[t])+size[c[t][0]]+1;
 80 }
 81 
 82 inline void dfs(int now)
 83 {
 84         for (int j=fir[now];j;j=next[j])
 85         {
 86                 int k=t[j];
 87                 dfs(k);
 88                 merge(k,now);
 89         }
 90         splay(now);
 91         long long tmp=find(now,m);
 92         ans=max(ans,able[now]*tmp);
 93 }
 94 
 95 inline void add(int x,int y)
 96 {
 97         t[++tot]=y; next[tot]=fir[x]; fir[x]=tot;
 98 }
 99 
100 int main()
101 {
102         //freopen("dispatch.in","r",stdin);
103         scanf("%d %d",&n,&m);
104         int x,y,z;
105         for (int i=1;i<=n;i++)
106         {
107                 scanf("%d %d %d",&x,&y,&z);
108                 if (x) add(x,i);else root=i;
109                 key[i]=y;
110                 able[i]=z;
111         }
112         dfs(root);
113         printf("%lld\n",ans);
114 }

 

转载于:https://www.cnblogs.com/zig-zag/archive/2013/03/28/2987825.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值