Codeforces768B-Code For 1-類似線段樹-枚舉+單點更新or區間更新
阿新 • • 發佈:2018-08-28
pre \n turn .net main std blog query amp
目錄
- Catalog
- Solution:
(有任何問題歡迎留言或私聊 && 歡迎交流討論哦
Catalog
Problem:Portal傳送門
?原題目描述在最下面。
?每次把\(n\)變成\(? \frac{n}{2}?,n\%2, ? \frac{n}{2}?\),直至 \(n\) 為\(1\) 或\(0\),問區間\(1\)的數量。
Solution:
?類似線段樹的結構,模擬線段樹即可。可以枚舉加單點更新也可以區間更新。
?\(R-L \leq 1e5, \; n \leq 2^{50}\)
?單點更新復雜度:\(log(n)\times1e5\)
?區間更新復雜度:\(log(n)\)
AC_Code:
#include<cstdio> #include<iostream> #include<cstring> #include<algorithm> #include<map> #include<queue> #include<set> #include<vector> #include<cmath> #include<bitset> #include<cassert> #define fi first #define se second #define all(x) (x).begin(),(x).end() #define mme(a,b) memset((a),(b),sizeof((a))) #define fuck(x) cout<<"* "<<x<<"\n" #define iis std::ios::sync_with_stdio(false) using namespace std; typedef pair<int,int> pii; typedef long long LL; const int MXN = 1e5 + 7; const int MXE = 1e6 + 7; const int mod = 998244353; const int INF = 0x3f3f3f3f; LL n, l ,r; /*****區間更新*****/ LL query(LL L,LL R,LL l,LL r,LL rt){ if(L>r||R<l)return 0; if(rt<2||l==r)return rt%2; LL mid = (l + r)/2, ans = 0; if(L>mid){ ans = query(L,R,mid+1,r,rt/2); }else if(R<mid){ ans = query(L,R,l,mid-1,rt/2); }else{ ans = query(L,mid-1,l,mid-1,rt/2)+query(mid+1,R,mid+1,r,rt/2)+query(mid,mid,mid,mid,rt%2); } return ans; } int main(){ while(~scanf("%lld%lld%lld", &n, &l, &r)){ LL ans = 0, m = n, len = 1; while(m > 1){ len = len<<1|1; m >>= 1; } printf("%lld\n", query(l,r,1,len,n)); } return 0; } /*****枚舉+單點更新*****/ int query(LL p,LL l,LL r,LL rt){ if(rt<2||l==r){ return rt; } LL mid = (l + r)/2; if(p==mid)return query(p,mid,mid,rt%2); else if(p<mid)return query(p,l,mid-1,rt/2); return query(p,mid+1,r,rt/2); } int main(){ while(~scanf("%lld%lld%lld", &n, &l, &r)){ LL ans = 0, m = n, len = 1; while(m>1){ len = len<<1|1; m >>= 1; } for(LL i = l; i <= r; ++i){ ans += query(i,1,len,n); } printf("%lld\n", ans); } return 0; }
Problem Description:
Codeforces768B-Code For 1-類似線段樹-枚舉+單點更新or區間更新