题目大意:每次加入一个数新的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;
}