标签:
题意:直接来链接吧http://acm.hdu.edu.cn/showproblem.php?pid=5358
思路:注意S(i,j)具有区间连续性且单调,而⌊log2x⌋具有区间不变性,于是考虑枚举⌊log2S(i,j)⌋的值,然后枚举i,从而能得到j的区间范围,然后统计答案即可。
另外这题比较坑,先枚举 ⌊log2S(i,j)⌋再枚举i 老是TLE,加了各种常数优化还是TLE,换成先枚举i再枚举⌊log2S(i,j)⌋就过了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 | #include <map>#include <set>#include <cmath>#include <ctime>#include <deque>#include <queue>#include <stack>#include <vector>#include <cstdio>#include <string>#include <cstdlib>#include <cstring>#include <iostream>#include <algorithm>using namespace std;#define X first#define Y second#define pb push_back#define mp make_pair#define all(a) (a).begin(), (a).end()#define fillchar(a, x) memset(a, x, sizeof(a))typedef long long ll;typedef pair<int, int> pii;typedef unsigned long long ull;#ifndef ONLINE_JUDGEvoid RI(vector<int>&a,int n){a.resize(n);for(int i=0;i<n;i++)scanf("%d",&a[i]);}void RI(){}void RI(int&X){scanf("%d",&X);}template<typename...R>void RI(int&f,R&...r){RI(f);RI(r...);}void RI(int*p,int*q){int d=p<q?1:-1;while(p!=q){scanf("%d",p);p+=d;}}void print(){cout<<endl;}template<typename T>void print(const T t){cout<<t<<endl;}template<typename F,typename...R>void print(const F f,const R...r){cout<<f<<", ";print(r...);}template<typename T>void print(T*p, T*q){int d=p<q?1:-1;while(p!=q){cout<<*p<<", ";p+=d;}cout<<endl;}#endiftemplate<typename T>bool umax(T&a, const T&b){return b<=a?false:(a=b,true);}template<typename T>bool umin(T&a, const T&b){return b>=a?false:(a=b,true);}template<typename T>void V2A(T a[],const vector<T>&b){for(int i=0;i<b.size();i++)a[i]=b[i];}template<typename T>void A2V(vector<T>&a,const T b[]){for(int i=0;i<a.size();i++)a[i]=b[i];}const double PI = acos(-1.0);const int INF = 1e9 + 7;/* -------------------------------------------------------------------------------- */#define f(a, b) (((a) + (b)) * ((b) - (a) + 1) / 2)int a[123456], minj[123456], maxj[123456];ll sum[123456];int main() {#ifndef ONLINE_JUDGE freopen("in.txt", "r", stdin); //freopen("out.txt", "w", stdout);#endif // ONLINE_JUDGE int T; cin >> T; while (T --) { int n; scanf("%d", &n); for (int i = 1; i <= n; i ++) { scanf("%d", a + i); sum[i] = sum[i - 1] + a[i]; } ll ans = 0; fillchar(minj, 0); fillchar(maxj, 0); for (int i = 1; i <= n; i ++) { ll now = sum[i - 1]; for (int t = 0; ; t ++) { ll Min = 1LL << t, Max = (1LL << (t + 1)) - 1; if (Min == 1) Min = 0; if (a[i] > Max) continue; while ((sum[minj[t]] - now < Min || minj[t] < i) && minj[t] <= n) minj[t] ++; while ((sum[maxj[t] + 1] - now <= Max || maxj[t] < i) && maxj[t] < n) maxj[t] ++; if (minj[t] > n) break; ll L = minj[t], R = maxj[t]; ans += (ll)(t + 1) * ((R - L + 1) * i + (L + R) * (R - L + 1) / 2); //print(i, t, L, R); } } cout << ans << endl; } return 0;} |
标签:
原文地址:http://www.cnblogs.com/jklongint/p/4709667.html