zoukankan      html  css  js  c++  java
  • 51nod 1674 区间的价值V2(思维+拆位+尺取法)

    最近被四区题暴虐。。。

    题意:lyk拥有一个区间。

    它规定一个区间的价值为这个区间中所有数and起来的值与这个区间所有数or起来的值的乘积。
    例如3个数2,3,6。它们and起来的值为2,or起来的值为7,这个区间对答案的贡献为2*7=14。
    现在lyk有一个n个数的序列,它想知道所有n*(n+1)/2个区间的贡献的和对1000000007取模后的结果是多少。
     
    区间的and值和区间的or值相乘,实际上等于将and值分解为2的幂次和的形式与or值分解成2的幂次和的形式相乘。
    所以对于同一段区间来说,是可以按位来统计的。
    首先将数列按位分解成32个位数列。
    枚举区间的左端点,,区间的and值要对答案有贡献必须为1,随着右端点右移,and值为不递增的,而区间的or值要对答案有贡献必须为1,随着右端点右移,or值为不递减的。
    找到这两个满足条件的最大区间的交集,即可统计出这段区间对答案的贡献。
    先用尺取法进行预处理,再依此统计答案。
    时间复杂度O(n*loga*loga)。
     
    # include <cstdio>
    # include <cstring>
    # include <cstdlib>
    # include <iostream>
    # include <vector>
    # include <queue>
    # include <stack>
    # include <map>
    # include <bitset>
    # include <set>
    # include <cmath>
    # include <algorithm>
    using namespace std;
    # define lowbit(x) ((x)&(-x))
    # define pi acos(-1.0)
    # define eps 1e-8
    # define MOD 1000000007
    # define INF 1000000000
    # define mem(a,b) memset(a,b,sizeof(a))
    # define FOR(i,a,n) for(int i=a; i<=n; ++i)
    # define FO(i,a,n) for(int i=a; i<n; ++i)
    # define bug puts("H");
    # define lch p<<1,l,mid
    # define rch p<<1|1,mid+1,r
    # define mp make_pair
    # define pb push_back
    typedef pair<int,int> PII;
    typedef vector<int> VI;
    # pragma comment(linker, "/STACK:1024000000,1024000000")
    typedef long long LL;
    inline int Scan() {
        int x=0,f=1; char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-') f=-1; ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0'; ch=getchar();}
        return x*f;
    }
    inline void Out(int a) {
        if(a<0) {putchar('-'); a=-a;}
        if(a>=10) Out(a/10);
        putchar(a%10+'0');
    }
    const int N=100005;
    //Code begin...
    
    int R[32][N], L[32][N], n, mod[65];
    LL ans;
    bool wei[32][N];
    
    void init(){
        mod[0]=1; FOR(i,1,64) mod[i]=(mod[i-1]<<1)%MOD;
        FO(i,0,32) {
            int l=1, r=1;
            while (l<=n) {
                if (!wei[i][l]) L[i][l]=0;
                else {
                    r=max(r,l);
                    while (r<n&&wei[i][r+1]) ++r;
                    L[i][l]=r;
                }
                ++l;
            }
        }
        FO(i,0,32) {
            int l=1, r=1;
            while (l<=n) {
                if (wei[i][l]) R[i][l]=l;
                else {
                    r=max(l,r);
                    while (r<=n&&!wei[i][r]) ++r;
                    R[i][l]=r;
                }
                ++l;
            }
        }
    }
    void sol(){
        FO(i,0,32) FOR(j,1,n) {
            if (!wei[i][j]) continue;
            FO(k,0,32) {
                if (R[k][j]>L[i][j]) continue;
                ans=(ans+(LL)(L[i][j]-R[k][j]+1)*mod[i+k])%MOD;
            }
        }
    }
    int main ()
    {
        int x;
        n=Scan();
        FOR(i,1,n) {
            x=Scan();
            FO(j,0,32) wei[j][i]=x%2, x/=2;
        }
        init();
        sol();
        printf("%lld
    ",ans);
        return 0;
    }
    View Code
     
     
  • 相关阅读:
    又来项目了,星座运势widget
    ubuntu下编译android源代码
    Android UI,界面辅助设置工具,可随意拖动控件,比google官方提供的方便
    Android 1.5原生软件开发SDK公布
    REST转自WIKI
    Android SDK 1.5 包装索引
    android google market FreshFace上线了,大家都试用试用,反正免费的
    JSON
    ubuntu命令
    网站支付宝接口错误代码:TRADE_DATA_MATCH_ERROR怎么处理? uz
  • 原文地址:https://www.cnblogs.com/lishiyao/p/7128453.html
Copyright © 2011-2022 走看看