codeforces 875D

http://codeforces.com/contest/875/problem/D

题意:给你 n 个长度的数组,求一共有多少区间 [ l ,  r ] ,使区间 [ l ,  r ] 所有数字的 或 运算大于所有区间 [ l ,  r ] 的数。

题解:RMQ+分治。

   找到 区间 [ l ,  r ] 内最大值 a,和最接近 a 的数 b 且(b|a>a),左边的数为 lb,右边的数为rb,经过 a 的区间可以 o(1)求出。分治 a 的两边。

#include<cstdio>
#include<string>
#include<cmath>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<set>
#define oo 0x3f3f3f3f
#define mod 1000000007
using namespace std;
const int MAXN = 200000+10;
int dp[MAXN][20];
int a[MAXN];
vector<int> ve[35];
void RMQ_max_init( int n )
{
    memset(dp, 0x00, sizeof(dp));
    for(int i = 1; i <= n; i++)
        dp[i][0] = i;
    for(int j = 1; (1<<j) <= n; j++)
        for(int i = 1; i+(1<<j)-1 <= n; i++)
            if( a[ dp[i][j-1] ] < a[ dp[i+(1<<(j-1))][j-1] ])
                dp[i][j] = dp[i+(1<<(j-1))][j-1];
            else
                dp[i][j] = dp[i][j-1];
}
int RMQ_max( int L, int R )
{
    int k = 0;
    while( (1<<(k+1)) <= R-L+1 )
        k++;
    if(a[ dp[L][k] ] < a[ dp[R-(1<<k)+1][k] ]) return dp[R-(1<<k)+1][k];
    return dp[L][k];
}
void init(int x, int id)
{
    for(int i = 0; (1<<i) <= x; ++i)
    {
        if(x&(1<<i)) ve[i].push_back(id); 
    }
}
long long ans;
void dfs(int l, int r, int n)
{
    if(l>=r) return ;
    int mid = RMQ_max(l, r);
    int left = 0, right = n+1;
    for(int i = 0; (1<<i)<=1e9; ++i)
    {
        if(!(a[mid]&(1<<i)))
        {
            int k = lower_bound(ve[i].begin(), ve[i].end(), mid)-ve[i].begin();
            if(k < ve[i].size() && ve[i][k]>mid) right = min(right, ve[i][k] );
            --k;
            if(k>=0 && k < ve[i].size() && ve[i][k] < mid) left = max(left, ve[i][k]);
        }
    }
    if(left != 0 && left >= l)
    {
        ans += (long long)(left-l+1)* (long long)(r-mid+1);
    }
    if(right != n+1 && right <= r)
    {
        ans += (long long)(mid-l+1)* (long long)(r-right+1);
    }
    if(left != 0 && left >= l && right != n+1 && right <= r)
    {
        ans -= (long long)(left-l+1)* (long long)(r-right+1);
    }
    dfs(l, mid-1, n);
    dfs(mid+1, r, n);
}
int main (void)
{
    ios::sync_with_stdio(false);
    int n; cin >> n; 
    for(int i = 1; i <= n; ++i)
    {
        cin >> a[i];
        init( a[i], i );
    }
    RMQ_max_init(n);
    ans = 0;
    dfs(1, n, n);
    cout << ans;
}
原文地址:https://www.cnblogs.com/lkcc/p/7683969.html