codeforces 876F High Cry (思维,位运算)

来源:互联网 发布:ghostview mac 编辑:程序博客网 时间:2024/06/03 17:07

D. High Cry

Disclaimer: there are lots of untranslateable puns in the Russian version of the statement, so there is one more reason for you to learn Russian :)

Rick and Morty like to go to the ridge High Cry for crying loudly — there is an extraordinary echo. Recently they discovered an interesting acoustic characteristic of this ridge: if Rick and Morty begin crying simultaneously from different mountains, their cry would be heard between these mountains up to the height equal the bitwise OR of mountains they've climbed and all the mountains between them.

Bitwise OR is a binary operation which is determined the following way. Consider representation of numbers x and y in binary numeric system (probably with leading zeroes) x = xk... x1x0 and y = yk... y1y0. Then z = x | y is defined following way: z = zk... z1z0, where zi = 1, if xi = 1 or yi = 1, and zi = 0 otherwise. In the other words, digit of bitwise OR of two numbers equals zero if and only if digits at corresponding positions is both numbers equals zero. For example bitwise OR of numbers 10 = 10102 and 9 = 10012 equals 11 = 10112. In programming languages C/C++/Java/Python this operation is defined as «|», and in Pascal as «or».

Help Rick and Morty calculate the number of ways they can select two mountains in such a way that if they start crying from these mountains their cry will be heard above these mountains and all mountains between them. More formally you should find number of pairs l and r (1 ≤ l < r ≤ n) such that bitwise OR of heights of all mountains between l and r (inclusive) is larger than the height of any mountain at this interval.

Input

The first line contains integer n (1 ≤ n ≤ 200 000), the number of mountains in the ridge.

Second line contains n integers ai (0 ≤ ai ≤ 109), the heights of mountains in order they are located in the ridge.

Output

Print the only integer, the number of ways to choose two different mountains.


解题思路:当正面分析不容易得到答案的时候我们很容易想到分析不满足条件的答案个数。

然后我们再来想什么样的情况是不满足条件的呢?

说明这个区间里面所有的数只有最大的那个数所包含的二进制1.

例如一个数 7 二进制 111

那么这个区间里面的数只能是 001 010 100... 而不能是1000.

所以到这里我们可以显而易见的看到我们需要针对每个二进制位进行讨论。

所以我们需要记录每一个二进制位上的1在当前数字前最近的出现位置,还有在当前数字后最近出现的位置。


Trick:需要考虑有相等的数字的情况,为了避免重复计数我们需要维护当前数字上一个出现的位置。


AC代码:

/** @Author: wchhlbt* @Last Modified time: 2017-11-01*/#include <bits/stdc++.h>#define inf 0x3f3f3f3f#define pb push_back#define AA first#define BB second#define ONES(x) __builtin_popcount(x)#define _  << "  " <<using namespace std;typedef pair<int, int> P;typedef long long ll ;int dx[4] = {0,0,1,-1};int dy[4] = {1,-1,0,0};const double eps =1e-8;const int mod = 1000000007;const double PI = acos(-1.0);inline int read(){ int num;    scanf("%d",&num);   return num;}const int maxn = 200007;int a[maxn];int l[maxn];//维护每个数字能掌控的左边界int r[maxn];//                  右边界int lbit[35];//维护每个位置上的1前一个出现的位置int rbit[35];//                后map<int,int> L;//维护每个数字上一个出现的位置int main(){    int n  = read();    for(int i = 1; i<=n; i++)   a[i] = read();    memset(lbit,0,sizeof lbit);    memset(rbit,inf,sizeof rbit);    for(int i = 1; i<=n; i++){        l[i] = L[a[i]];        for(int j = 0; j<32; j++){            if(a[i]&(1<<j))                lbit[j] = i;            else                l[i] = max(lbit[j],l[i]);        }        L[a[i]] = i;    }    for(int i = n; i>=1; i--){        r[i] = n+1;        for(int j = 0; j<32; j++){            if(a[i]&(1<<j))                rbit[j] = i;            else                r[i] = min(rbit[j],r[i]);        }    }    ll ans = 1ll*n*(n+1)/2;//这里会爆int 这里存放的是两个端点可能相同的情况数    for(int i = 1; i<=n; i++){        ll t1,t2;        t1 = i-l[i];        t2 = r[i] - i;        ans -= (t1*t2);        //cout << i _ l[i] _ r[i] _ ans << endl;    }    cout << ans << endl;    return 0;}


原创粉丝点击