您的位置:首页 > 其它

HDU - 6161 - Big binary tree

2017-08-23 21:16 405 查看
HDU - 6161 - Big binary tree

通过一个点的最大权值的链可以通过维护每个点到叶子的最大权值得到,方法就是一直把这个点向上提。

因此考虑维护每个点到叶子的最大权值 f 。

如果 u 的子树没有发生过修改:因为是一棵完全二叉树,所以一直往左走的深度-一直往右走的深度≥1。如果深度相同,肯定一直往左走,如果大1:

往左走:an=x2n,Sn=x(2n−1) 。

往右走:

an=2an−1+1

an+1=2an−1+2

an+1=(x+1)2n

Sn+n=(x+1)(2n−1)

Sn=(x+1)(2n−1)−n

作差得

Sn=x(2n−1)−(x+1)(2n−1−1)+n−1=x2n−1−2n−1+n=(x−1)2n+n≥0 。

所以一直往左走肯定比一直往右走高,所以从 n 点开始往上移。

每发生一次修改,可以向上维护一条链的 f 值。因为最多修改 mlogn 条链,放到
map
中维护就行了。

#include<bits/stdc++.h>
#define ls(x) (x<<1)
#define rs(x) ((x)<<1|1)
using namespace std;
typedef long long ll;
unordered_map<int,ll> f(3500000),val(3500000);
int n;
ll cal(int x)
{
if(x>n) return 0;
if(f.count(x)) return f[x];
int t=x,cl=0,cr=0;
while(t<=n) ++cl,t=ls(t);
t=x;
while(t<=n) ++cr,t=rs(t);
t>>=1;
if(cr!=cl) t=n;
ll res=0;
while(t>=x) res+=t,t>>=1;
return res;
}
void modify(int u,ll x)
{
val[u]=x;
while(u>=1)
{
f[u]=max(cal(ls(u)),cal(rs(u)))+(val.count(u)?val[u]:u);
u>>=1;
}
}
ll query(int x)
{
ll res=cal(ls(x))+cal(rs(x))+(val.count(x)?val[x]:x);
ll d=max(cal(ls(x)),cal(rs(x)))+(val.count(x)?val[x]:x);
while((x>>1)>=1)
{
bool L=(x&1)?1:0;
x>>=1;
d+=val.count(x)?val[x]:x;
res=max(res,d+(L?cal(ls(x)):cal(rs(x))));
}
return res;
}
int main()
{
int m;
while(~scanf("%d%d",&n,&m))
{
f.clear();val.clear();
char op[10];
while(m--)
{
scanf("%s",op);
if(op[0]=='q')
{
int x;scanf("%d",&x);
printf("%I64d\n",query(x));
}
else
{
int u;ll x;
scanf("%d%I64d",&u,&x);
modify(u,x);
}
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: