您的位置:首页 > 其它

51Nod-1674-区间的价值 V2

2016-12-26 20:04 393 查看
ACM模版

描述



题解

虽然是四级题,但是真不会,找了题解,甚是不错。

以下题解来自abclzr的博客:

对区间分治,统计
[l, r]
中经过mid的区间的答案。

我的做法是从mid向右扫到r,统计出所有
[mid, i], mid ≤ i ≤ r
的and和or值。

然后发现这些
and
or
值有很多相同的,把相同的压在一起并记录sum,再从
mid - 1
扫到
l
并暴力从
mid
向右统计答案。

事实上因为
[mid, i], mid ≤ i ≤ r
是连续的,所以压完后的个数是
O(2loga)
(a为10^9)。这样时间复杂度是
O(nlognloga)


代码

#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

typedef long long ll;

int cinDiy()
{
int k = 0;
char c = getchar();
for (; c < '0' || c > '9'; c = getchar()) ;
for (; c >= '0' && c <= '9'; c = getchar())
{
k = k * 10 + c - 48;
}
return k;
}

const ll MOD = 1e9 + 7;
const int MAXN = 1e5 + 10;

int a[MAXN];
int AND[MAXN];
int OR[MAXN];
int sum[MAXN], resA, resO;
ll ans = 0;

void solve(int l, int r)
{
if (l == r)
{
return ;
}
int mid = (l + r + 1) >> 1;

ll pos = mid;
AND[pos] = OR[pos] = a[mid];
sum[pos] = 1;
for (int i = mid + 1; i <= r; ++i)
{
if (((AND[pos] & a[i]) != AND[pos]) || ((OR[pos] | a[i]) != OR[pos]))
{
++pos;
AND[pos] = AND[pos - 1] & a[i];
OR[pos] = OR[pos - 1] | a[i];
sum[pos] = 1;
}
else
{
++sum[pos];
}
}

resA = resO = a[mid - 1];
for (int i = mid - 1; i >= l; --i)
{
resA &= a[i];
resO |= a[i];
for (int j = mid; j <= pos; ++j)
{
ans = (ans + (ll)(resA & AND[j]) * (ll)(resO | OR[j]) % MOD * (ll)(sum[j]) % MOD) % MOD;
}
}

solve(l, mid - 1);
solve(mid, r);
}

int main()
{
int n;
n = cinDiy();
for (int i = 1; i <= n; ++i)
{
a[i] = cinDiy();
ans = (ans + 1ll * a[i] * a[i]) % MOD;  //  序列[i, i]
}

solve(1, n);
printf("%d\n", (int)ans);

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  位运算 区间