您的位置:首页 > 理论基础 > 数据结构算法

hdu 5975 树状数组原理题(2016ACM/ICPC亚洲区大连站)

2017-06-09 16:34 429 查看
题目大意:每次加入一个数新的i,是把[i-lowbit(i)+1,i]的数字都加入集合。每把一个数加入到一个集合内,都要花费一单位能量。统计花费的能量数。

操作1:把[L,R]的数字依此加入,统计出所有的能量话费。

操作2:询问一个X,查询X在1~n的插入中一共被移动了多少次。

思路:

直接算:

long long ans = 0;
for(int i=a;i<=b;i++)
ans+=lowbit(i);
cout<<ans<<endl;这样会TLE。
操作1:树状数组的原理相当于每个位置放的都是1,奇数位都是1,偶数根据所在位置,依此为2,4,8,16。。。

所以,只需转化为二进制后第0位知道第n位1出现的个数,再乘对应的2,4,8。。。就好了。

ll get_ans(ll x)
{
ll ans = 0,t = 1,tt;
for(int i=0;(t<<i)<=x;i++)
{
tt = x/(t<<i);
tt -= x/(t<<(i+1));
tt *= (t<<i);
ans += tt;
//cout<<ans<<' ';
}
//cout<<endl;
return ans;
}

操作2:
考虑树状数组,转化为x被树状数组中1-n的下标中哪些所覆盖了,直接累加lowbit就行。

(7=111,

那么lowbit为1的有几个?

001,011,101,111

奇数为(n+1)>>1;

偶数为n>>1;)

while(a<=n)
{
ans++;
a += lowbit(a);
}
//
//  main.cpp
//  160929
//
//  Created by 刘哲 on 17/5/30.
//  Copyright © 2016年 my_code. All rights reserved.
//#include <bits/stdc++.h>

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <string.h>
#include <map>
#include <set>
#include <queue>
#include <deque>
#include <list>
#include <bitset>
#include <stack>
#include <stdlib.h>
#define lowbit(x) (x&-x)
typedef long long ll;
typedef long long LL;
using namespace std;
ll get_ans(ll x)
{
ll ans = 0,t = 1,tt;
for(int i=0;(t<<i)<=x;i++)
{
tt = x/(t<<i);
tt -= x/(t<<(i+1));
tt *= (t<<i);
ans += tt;
//cout<<ans<<' ';
}
//cout<<endl;
return ans;
}
int main()
{
//get_ans(9);
ll n,q;
int op;
ll a,b;
// while(cin>>n>>q)
while(~scanf("%lld%lld",&n,&q))
{
while(q--)
{
//cin>>op;
scanf("%d",&op);
if(op==1)
{
ll ans = 0;
//cin>>a>>b;
scanf("%lld%lld",&a,&b);
ans = get_ans(b)-get_ans(a-1);
//cout<<ans<<endl;
printf("%lld\n",ans);
}
else
{
ll ans = 0;
//cin>>a;
scanf("%lld",&a);
while(a<=n)
{
ans++;
a += lowbit(a);
}
//cout<<ans<<endl;
printf("%lld\n",ans);
}
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐