/*
最长距离
1 .当前x 为根节点的最长直径 ,或 一层一层往上走 包含x的一边 ,加另一部分最长半径。
设 ans[x] 为 以x 为根节点的 最长半径,
chance x, 只影响 x 和x 的祖先。
未影响的 ans 选择 最右的路径 或 从 n 往上爬 看是否爬到 x
*/
#include<iostream>
#include<algorithm>
#include<map>
#include<cstdio>
#include<cstring>
typedef long long ll;
#define ms(a) memset(a,0,sizeof(a))
#define rep(i,a,b) for(int i=(a);i<=(b);++ i)
#define Bug(x) cout<<x<<' '<<":)->ok"<<endl;
using namespace std;
map<int,ll> val,ans;
int n,m;
ll Ans=0;
ll Value(int x)
{
if(val.count(x)) return val[x];
return x;
}
ll path(int x)
{
if(ans.count(x)) return ans[x];
if(x>n) return 0;
ll s1=0,s2=0;
int xx=x,nn=n;
while(xx<=n)
{
s1 +=xx;
xx =2*xx+1;
}
while(nn>x)
{
s2 +=nn;
nn /=2;
}
return max(s1,nn==x?s2+x:0);
}
void query(int x)
{
Ans=0;
int root=x;
ll al,ar,s1=0,f=2,s2;
while(root)
{
s1 +=Value(root);
s2=s1;
if(f!=0) s2 +=path(root*2);
if(f!=1) s2 +=path(root*2+1);
Ans = max(Ans,s2);
if(f==2) s1 +=max(path(root*2),path(root*2+1));
f =root&1;
root >>=1;
}
}
void change(int x,ll x1)
{
val[x] =x1;
ans[x]= x1 + max(path(x*2),path(x*2+1));
x /=2;
while(x)
{
ans[x] = Value(x) +max( path(x*2) , path(x*2+1) );
x /=2;
}
}
int main()
{
while(~scanf("%d%d",&n,&m))
{
ans.clear();
val.clear();
char que[10];
int x;
ll x1;
while(m--)
{
scanf("%s",que);
if(que[0]=='q')
{
scanf("%d",&x);
query(x);
printf("%lld\n",Ans);
}
else
{
scanf("%d%lld",&x,&x1);
change(x,x1);
}
}
}
return 0;
}
07-13
07-13
07-13
“相关推荐”对你有帮助么?
-
非常没帮助
-
没帮助
-
一般
-
有帮助
-
非常有帮助
提交