2017.9.14 dispatching 思考记录
2017-09-14 00:36
190 查看
看发表时间不知道的以为是美国人
这个题是要求出一个点作为管理,那我们就可以枚举这个点
然后再在他的子树中从小到大累加,统计个数,知道>m为止
由于涉及到维护大小、这种大小关系的合并,所以我们考虑splay以及splay启发式合并
于是就用splay维护size、点的花费,splay子树的花费和
注意空间重复利用,不然开销是nlogn的,会mle
没卡nlog^2n十分良心
splay好久没写凭感觉打竟然是对的
听说左偏树或斜堆几十行就搞定了、但对于熟悉splay的玩家来说应该写splay会比较稳?反正我不熟
注意:splay上找的时候一定注意全面
注意几个if之间有没有else
码:
#include<iostream>
#include<cstdio>
using namespace std;
#include<cstring>
#define N 100005
int c
,v1
,n,sz[1000009],ch[1000009][2],fu
,rt
,cnt,m,tot,hou[N<<1],xia
,zhong[N<<1];
long long ans,vv[1000009],v[1000009];
void up(int o)
{
vv[o]=vv[ch[o][0]]+vv[ch[o][1]]+v[o];
sz[o]=sz[ch[o][0]]+sz[ch[o][1]]+1;
}
void set(int o,int wh,int t)
{
ch[o][wh]=t;
if(t!=0)fu[t]=o;
up(o);
}
int getwh(int o)
{
return ch[fu[o]][1]==o;
}
void rotate(int o)
{
int fa=fu[o],ye=fu[fu[o]];
int wh=getwh(o);
set(fa,wh,ch[o][wh^1]);
set(o,wh^1,fa);
fu[o]=ye;
if(ye!=0) ch[ye][ch[ye][1]==fa?1:0]=o;
}
void splay(int o,int tar,int z)
{
for(;fu[o]!=tar;rotate(o))
if(fu[fu[o]]!=0)
getwh(fu[o])==getwh(o)?rotate(fu[o]):rotate(o);
if(tar==0)rt[z]=o;
}
void ins(int o,int val,int yy)
{
int lin=o;
if(yy==0)
{
sz[++cnt]=1;
v[cnt]=val;
vv[cnt]=val;
sz[cnt]=1;
yy=cnt;
}else
{
vv[yy]=v[yy];
sz[yy]=1;
ch[yy][0]=ch[yy][1]=0;
fu[yy]=0;
}
o=rt[o];
int last=0;
while(o!=0)
{
last=o;
if(val<=v[o])o=ch[o][0];
else o=ch[o][1];
}
if(last==0)
{
rt[lin]=o;
return;
}
if(v[last]<val)set(last,1,yy);
else set(last,0,yy);
splay(yy,0,lin);
}
int cha(int o)
{
int ys=m;
o=rt[o];
int ans=0;
while(o)
{
if(vv[ch[o][0]]+v[o]==ys)
{
ans+=sz[ch[o][0]]+1;
break;
}else
if(vv[ch[o][0]]+v[o]>ys)
{
o=ch[o][0];
}else
if(vv[ch[o][0]]+v[o]<ys)
{
ans+=sz[ch[o][0]]+1;
ys-=vv[ch[o][0]]+v[o];
o=ch[o][1];
}
}
return ans;
}
void jian(int a,int b)
{
++tot,hou[tot]=xia[a],xia[a]=tot,zhong[tot]=b;
}
void jia(int a,int b)
{
jian(a,b);
jian(b,a);
}
void bianli(int o,int mb)
{
if(o==0)return;
bianli(ch[o][0],mb);
bianli(ch[o][1],mb);
ins(mb,v[o],o);
}
int js;
void dfs(int o,int fa)
{
++js;
int i;
++cnt;
rt[o]=cnt;
v[cnt]=c[o];
sz[cnt]=1;
vv[cnt]=c[o];
for(i=xia[o];i!=-1;i=hou[i])
{
int nd=zhong[i];
if(nd==fa)continue;
dfs(nd,o) ;
if(sz[rt[o]]>sz[rt[nd]])
{
bianli(rt[nd],o);
}else
{
bianli(rt[o],nd);
rt[o]=rt[nd];
}
}
ans=max(ans,1ll*cha(o)*1ll*v1[o]);
}
int main()
{
int i,x;
memset(xia,-1,sizeof(xia));
scanf("%d%d",&n,&m);
for(i=1;i<=n;i++)
{
scanf("%d%d%d",&x,&c[i],&v1[i]);
if(x!=0)jia(x,i);
}
dfs(1,1);
printf("%lld",ans);
}
这个题是要求出一个点作为管理,那我们就可以枚举这个点
然后再在他的子树中从小到大累加,统计个数,知道>m为止
由于涉及到维护大小、这种大小关系的合并,所以我们考虑splay以及splay启发式合并
于是就用splay维护size、点的花费,splay子树的花费和
注意空间重复利用,不然开销是nlogn的,会mle
没卡nlog^2n十分良心
splay好久没写凭感觉打竟然是对的
听说左偏树或斜堆几十行就搞定了、但对于熟悉splay的玩家来说应该写splay会比较稳?反正我不熟
注意:splay上找的时候一定注意全面
注意几个if之间有没有else
码:
#include<iostream>
#include<cstdio>
using namespace std;
#include<cstring>
#define N 100005
int c
,v1
,n,sz[1000009],ch[1000009][2],fu
,rt
,cnt,m,tot,hou[N<<1],xia
,zhong[N<<1];
long long ans,vv[1000009],v[1000009];
void up(int o)
{
vv[o]=vv[ch[o][0]]+vv[ch[o][1]]+v[o];
sz[o]=sz[ch[o][0]]+sz[ch[o][1]]+1;
}
void set(int o,int wh,int t)
{
ch[o][wh]=t;
if(t!=0)fu[t]=o;
up(o);
}
int getwh(int o)
{
return ch[fu[o]][1]==o;
}
void rotate(int o)
{
int fa=fu[o],ye=fu[fu[o]];
int wh=getwh(o);
set(fa,wh,ch[o][wh^1]);
set(o,wh^1,fa);
fu[o]=ye;
if(ye!=0) ch[ye][ch[ye][1]==fa?1:0]=o;
}
void splay(int o,int tar,int z)
{
for(;fu[o]!=tar;rotate(o))
if(fu[fu[o]]!=0)
getwh(fu[o])==getwh(o)?rotate(fu[o]):rotate(o);
if(tar==0)rt[z]=o;
}
void ins(int o,int val,int yy)
{
int lin=o;
if(yy==0)
{
sz[++cnt]=1;
v[cnt]=val;
vv[cnt]=val;
sz[cnt]=1;
yy=cnt;
}else
{
vv[yy]=v[yy];
sz[yy]=1;
ch[yy][0]=ch[yy][1]=0;
fu[yy]=0;
}
o=rt[o];
int last=0;
while(o!=0)
{
last=o;
if(val<=v[o])o=ch[o][0];
else o=ch[o][1];
}
if(last==0)
{
rt[lin]=o;
return;
}
if(v[last]<val)set(last,1,yy);
else set(last,0,yy);
splay(yy,0,lin);
}
int cha(int o)
{
int ys=m;
o=rt[o];
int ans=0;
while(o)
{
if(vv[ch[o][0]]+v[o]==ys)
{
ans+=sz[ch[o][0]]+1;
break;
}else
if(vv[ch[o][0]]+v[o]>ys)
{
o=ch[o][0];
}else
if(vv[ch[o][0]]+v[o]<ys)
{
ans+=sz[ch[o][0]]+1;
ys-=vv[ch[o][0]]+v[o];
o=ch[o][1];
}
}
return ans;
}
void jian(int a,int b)
{
++tot,hou[tot]=xia[a],xia[a]=tot,zhong[tot]=b;
}
void jia(int a,int b)
{
jian(a,b);
jian(b,a);
}
void bianli(int o,int mb)
{
if(o==0)return;
bianli(ch[o][0],mb);
bianli(ch[o][1],mb);
ins(mb,v[o],o);
}
int js;
void dfs(int o,int fa)
{
++js;
int i;
++cnt;
rt[o]=cnt;
v[cnt]=c[o];
sz[cnt]=1;
vv[cnt]=c[o];
for(i=xia[o];i!=-1;i=hou[i])
{
int nd=zhong[i];
if(nd==fa)continue;
dfs(nd,o) ;
if(sz[rt[o]]>sz[rt[nd]])
{
bianli(rt[nd],o);
}else
{
bianli(rt[o],nd);
rt[o]=rt[nd];
}
}
ans=max(ans,1ll*cha(o)*1ll*v1[o]);
}
int main()
{
int i,x;
memset(xia,-1,sizeof(xia));
scanf("%d%d",&n,&m);
for(i=1;i<=n;i++)
{
scanf("%d%d%d",&x,&c[i],&v1[i]);
if(x!=0)jia(x,i);
}
dfs(1,1);
printf("%lld",ans);
}
相关文章推荐
- 2017.9.14 棘手的操作 思考记录
- 2017.9.14 仪仗队 思考记录
- 聊天记录——关于怀疑,思考,验证的进一步讨论
- 天天记录 - Andorid Invalidate 引发的思考
- charindex使用一个异常记录思考
- canvas-shooting-game 记录与思考
- [生而为人-思考] Knowledge Cooking -5th 分享会记录
- 2017.3.25 SJY摆石子 思考记录
- 2017.9.24 虔诚的墓主人 思考记录
- 2017.9.28 约数研究 思考记录
- 2017.9.28 产品加工 思考记录
- 2017.10.1 互不侵犯king 思考记录
- 2017.4.19 细胞分裂 思考记录
- 2010webRebuild 大会 广州站记录 & 后记 (在职前端人员的发展与思考)
- 2017.10.17 CF#441 F题 思考记录
- bzoj 4942 整数 思考记录
- 2017.10.23 chess 中国象棋 思考记录
- 记录Android微信分享功能的吐槽与思考
- 阅读 思考 感悟 记录 升华 幸福
- 2017.10.26 星际贸易 思考记录