CF 768B

CF 768B
題意:
In each operation Sam must remove any element x, such that x>1, from the list and insert at the same position x/2,x%2,x/2 sequentially. He must continue with these operations until all the elements in the list are either 0 or 1.
給定一個數N,對大於1的數在原來的位置拆分爲N/2,N%2,N/2三個數。對拆分出的大於1的數一樣進行拆分,直至全部的數均爲0或1。
Now the masters want the total number of 1s in the range l to r (1-indexed).
對拆分後的0/1序列,詢問L到R區間中1的數量

相似於線段樹的區間查詢
思路1:簡單題,遞歸思想。對於給定的N,能夠計算出最終0/1序列的長度。遞歸模擬,一層層往下分解,將獲得的數分解到序列的對應指定位置中,當沒法分解時則返回值,最後遞歸獲得區間內全部的1的個數
      這裏我擔憂被卡,用了一個位運算小優化。其實不用也能夠。
Code:
#include<cstdio>
typedef long long ll;
ll n,ql,qr,len=1,ans;
ll dfs(ll n,ll l,ll r){
    if(n==0||l>qr||r<ql) return 0;
    if(n==1) return 1;
    ll mid=l+r>>1;
    return dfs(n>>1,l,mid-1)+dfs(n&1,mid,mid)+dfs(n>>1,mid+1,r);
}
int main(){
    scanf("%I64d%I64d%I64d",&n,&ql,&qr);
    for(ll x=n;x>1;x>>=1,len=len<<1|1);
    ans=dfs(n,1,len);
    printf("%I64d\n",ans);
    return 0;
}
思路2:求出區間端點的前綴和相減,拆分的個數符合f(n)=2*f(n-1)+1,而n拆後的區間和必定是n,因此用二分找出端點位置便可



優化

相關文章
相關標籤/搜索
本站公眾號
   歡迎關注本站公眾號,獲取更多信息