BZOJ 4750 密码安全

Posted on 2017-03-25 20:44  ziliuziliu  阅读(149)  评论(0编辑  收藏  举报

日常刷水。。。

单调栈,按位搞。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxn 100050
#define mod 1000000061
using namespace std;
long long t,n,a[maxn],l[maxn],r[maxn],cnt[maxn][31][2],s[maxn],top=0,sum[maxn];
long long read()
{
    char ch;long long data=0;
    while (ch<'0' || ch>'9') ch=getchar();
    while (ch>='0' && ch<='9')
    {
        data=data*10+ch-'0';
        ch=getchar();
    }
    return data;
}
void work(int x)
{
    for (int i=0;i<=30;i++) cnt[0][i][0]=1;
    n=read();
    for (long long i=1;i<=n;i++) {a[i]=read();sum[i]=sum[i-1]^a[i];}
    for (long long i=1;i<=n;i++)
        for (long long j=30;j>=0;j--)
        {
            cnt[i][j][0]=cnt[i-1][j][0];cnt[i][j][1]=cnt[i-1][j][1];
            cnt[i][j][((sum[i]&(1<<j))>0)]++;
        }
    top=0;
    for (long long i=1;i<=n;i++)
    {
        while (top && a[s[top]]<=a[i]) top--;
        l[i]=s[top]+1;s[++top]=i;
    }
    top=0;
    for (long long i=n;i>=1;i--)
    {
        while (top && a[s[top]]<a[i]) top--;
        if (top) r[i]=s[top]-1;else r[i]=n;
        s[++top]=i;
    }
    long long ans=0;
    for (long long i=1;i<=n;i++)
        for (long long j=0;j<=30;j++)
        {
            long long bit;
            if (i==1) bit=cnt[r[i]][j][1]-cnt[i-1][j][1];
            else if (l[i]==1) bit=cnt[i-1][j][0]*(cnt[r[i]][j][1]-cnt[i-1][j][1])%mod+cnt[i-1][j][1]*(cnt[r[i]][j][0]-cnt[i-1][j][0])%mod;
            else bit=(cnt[i-1][j][0]-cnt[l[i]-2][j][0])*(cnt[r[i]][j][1]-cnt[i-1][j][1])%mod+(cnt[i-1][j][1]-cnt[l[i]-2][j][1])*(cnt[r[i]][j][0]-cnt[i-1][j][0])%mod;
            bit%=mod;
            ans+=bit*((1<<j)%mod)%mod*a[i]%mod;ans%=mod;
        }
    printf("%lld\n",ans);
}
int main()
{
    t=read();
    for (long long i=1;i<=t;i++) work(i);
    return 0;
}