BIT WISE AND 的完美正方形
The Perfect Square with BIT WISE AND
子数组按位AND运算时,如何优化计算连续子数组的完全平方数的解。
时间复杂度应为 O(n) 或 O(n*logn)。
这是天真的方法
int a[]={1,2,3,4,5,6};
int l=2,r=5;
int c=0; // for counting the subsets
for(int i=l;i<=r;i++){
int val=a[i];
for(int j=i;j<=r;j++){
val=val&a[j];
if(isPerfectSquare(val)){
c+=1;
}
}
}
你可以创建一个数位的 Trie 数据结构,然后继续插入 pre_and。此外,请记住让 Node 结构存储数字的索引,以便您可以对给定范围进行查询 运行。现在剩下的就是计算 AND 结果是否是一个完美的正方形。自己试试吧。暗示就够了。您可以参考this
ND 的数字最多可以更改 LogN 时间,因此最多可能有 O(NLogN) 个不同的值。因此可以更新组或范围内的答案,这可以通过线段树或分域树来完成。
#include <iostream>
#include <bits/stdc++.h>
#define ll long long
using namespace std;
int n, m, t, l, r, a[100005];
ll d[2][100005], ans[500005];
vector< pair<int, int> > rs[100005];
//vector for groups with equal AND
vector< pair<int, int> > groups;
//fenwick tree
ll sum(ll num, ll pos)
{
ll sm = 0;
while(pos >= 0)
{
sm += d[num][pos];
pos = (pos & (pos + 1)) - 1;
}
return sm;
}
void update(ll num, ll pos, ll x)
{
while(pos < n)
{
d[num][pos] += x;
pos = (pos | (pos + 1));
}
}
int main()
{
scanf("%d", &t);
while(t--)
{
scanf("%d", &n);
scanf("%d", &m);
for(int i = 0; i < n; i++)
{
scanf("%d", &a[i]);
d[0][i] = d[1][i] = 0;
rs[i].clear();
}
d[0][n] = d[1][n] = 0;
for(int i = 0; i < m; i++)
{
scanf("%d%d", &l, &r);
l--;
r--;
rs[r].push_back({l, i});
}
groups.clear();
for(int i = 0; i < n; i++)
{
//new vector for groups
vector< pair<int, int> > newgroups;
for(int j = 0; j < groups.size(); j++)
{
int cur = groups[j].first & a[i];
if(!j || cur != newgroups[newgroups.size() - 1].first)
{
newgroups.push_back({cur, groups[j].second});
}
}
if(newgroups.size() == 0 || newgroups[newgroups.size() - 1].first != a[i])
newgroups.push_back({a[i], i});
//making new vector current
groups = newgroups;
for(int j = 0; j < groups.size(); j++)
{
//checking for a perfect square
int sq = floor(sqrt(groups[j].first));
if((sq - 1) * (sq - 1) == groups[j].first || sq * sq == groups[j].first || (sq + 1) * (sq + 1) == groups[j].first)
{
//getting a borders
l = groups[j].second;
if(j != groups.size() - 1)
r = groups[j + 1].second - 1;
else
r = i;
//adding an arithmetic progression
update(0, l, (r + 1));
update(0, r + 1, -(r + 1));
update(1, l, 1);
update(1, r + 1, -1);
//adding on a prefix
update(0, 0, r - l + 1);
update(0, l, -(r - l + 1));
}
}
for(int j = 0; j < rs[i].size(); j++)
{
//getting an answer for a query
ans[rs[i][j].second] = sum(0, rs[i][j].first);
ans[rs[i][j].second] -= sum(1, rs[i][j].first) * rs[i][j].first;
}
}
for(int i = 0; i < m; i++)
{
printf("%lld\n", ans[i]);
}
}
return 0;
}
时间复杂度=O(QLogN+N∗LogA∗LogN)(setter的解法)
Space 复杂度=O(NLogAi) 其中 Ai 大约是 A 中的最大元素。
子数组按位AND运算时,如何优化计算连续子数组的完全平方数的解。 时间复杂度应为 O(n) 或 O(n*logn)。
这是天真的方法
int a[]={1,2,3,4,5,6};
int l=2,r=5;
int c=0; // for counting the subsets
for(int i=l;i<=r;i++){
int val=a[i];
for(int j=i;j<=r;j++){
val=val&a[j];
if(isPerfectSquare(val)){
c+=1;
}
}
}
你可以创建一个数位的 Trie 数据结构,然后继续插入 pre_and。此外,请记住让 Node 结构存储数字的索引,以便您可以对给定范围进行查询 运行。现在剩下的就是计算 AND 结果是否是一个完美的正方形。自己试试吧。暗示就够了。您可以参考this
ND 的数字最多可以更改 LogN 时间,因此最多可能有 O(NLogN) 个不同的值。因此可以更新组或范围内的答案,这可以通过线段树或分域树来完成。
#include <iostream>
#include <bits/stdc++.h>
#define ll long long
using namespace std;
int n, m, t, l, r, a[100005];
ll d[2][100005], ans[500005];
vector< pair<int, int> > rs[100005];
//vector for groups with equal AND
vector< pair<int, int> > groups;
//fenwick tree
ll sum(ll num, ll pos)
{
ll sm = 0;
while(pos >= 0)
{
sm += d[num][pos];
pos = (pos & (pos + 1)) - 1;
}
return sm;
}
void update(ll num, ll pos, ll x)
{
while(pos < n)
{
d[num][pos] += x;
pos = (pos | (pos + 1));
}
}
int main()
{
scanf("%d", &t);
while(t--)
{
scanf("%d", &n);
scanf("%d", &m);
for(int i = 0; i < n; i++)
{
scanf("%d", &a[i]);
d[0][i] = d[1][i] = 0;
rs[i].clear();
}
d[0][n] = d[1][n] = 0;
for(int i = 0; i < m; i++)
{
scanf("%d%d", &l, &r);
l--;
r--;
rs[r].push_back({l, i});
}
groups.clear();
for(int i = 0; i < n; i++)
{
//new vector for groups
vector< pair<int, int> > newgroups;
for(int j = 0; j < groups.size(); j++)
{
int cur = groups[j].first & a[i];
if(!j || cur != newgroups[newgroups.size() - 1].first)
{
newgroups.push_back({cur, groups[j].second});
}
}
if(newgroups.size() == 0 || newgroups[newgroups.size() - 1].first != a[i])
newgroups.push_back({a[i], i});
//making new vector current
groups = newgroups;
for(int j = 0; j < groups.size(); j++)
{
//checking for a perfect square
int sq = floor(sqrt(groups[j].first));
if((sq - 1) * (sq - 1) == groups[j].first || sq * sq == groups[j].first || (sq + 1) * (sq + 1) == groups[j].first)
{
//getting a borders
l = groups[j].second;
if(j != groups.size() - 1)
r = groups[j + 1].second - 1;
else
r = i;
//adding an arithmetic progression
update(0, l, (r + 1));
update(0, r + 1, -(r + 1));
update(1, l, 1);
update(1, r + 1, -1);
//adding on a prefix
update(0, 0, r - l + 1);
update(0, l, -(r - l + 1));
}
}
for(int j = 0; j < rs[i].size(); j++)
{
//getting an answer for a query
ans[rs[i][j].second] = sum(0, rs[i][j].first);
ans[rs[i][j].second] -= sum(1, rs[i][j].first) * rs[i][j].first;
}
}
for(int i = 0; i < m; i++)
{
printf("%lld\n", ans[i]);
}
}
return 0;
}
时间复杂度=O(QLogN+N∗LogA∗LogN)(setter的解法) Space 复杂度=O(NLogAi) 其中 Ai 大约是 A 中的最大元素。