题目链接
ps:十分有趣的一道题目。一直在想如何用lazy标记,来使区间更新不超时间。
有n个数(1 <= n <= 100000),数最大为2^63。有m次操作(1 <= m <= 100000) ,操作有一下两种:
- 使区间X到Y的所有数都开平方 (0)
- 输出区间X到Y的所有数的和 (1)
先输入n(10) 输入n(10)个数 输入m(5) 输入m(5)次操作 操作类型(0代表开方,1代表求值)以及X和Y代表区间的左右坐标 10 1 2 3 4 5 6 7 8 9 10 5 0 1 10 1 1 10 1 1 5 0 5 8 1 4 8
Case #1: 19 7 6
本题难在更新,在最开始时,对区间更新可以对区间内每一个点进行单点更新,但是复杂度极高。但是我们会发现即使是最大的2^63,在7次开方之后归1,且1开平方也是1。所以我们可以用一个标记来对树的节点进行标记。如果该节点范围内所有树都为1,则遇到开方操作可以无视。这样一来,我们就找到了优化更新的方法
#include
#include
#include
#include
using namespace std;
const int maxn = 1e5 + 10;
long long num[maxn];
struct Tree
{
int lson , rson ;
long long sum;
bool is1;
}tree[maxn * 4];
void Push_one(int h)
{
tree[h].is1 = tree[h << 1].is1 && tree[h << 1 | 1].is1;
}
void Build (int l , int r ,int h)
{
tree[h].lson = l;
tree[h].rson = r;
if (l == r)
{
if (num[l] == 1)
tree[h].is1 = true;
else
tree[h].is1 = false;
tree[h].sum = num[l];
return;
}
int mid = (l + r) >> 1;
Build (l , mid , h << 1) ;
Build (mid + 1 , r , h << 1 | 1);
tree[h].sum = tree[h << 1].sum + tree[h << 1 | 1].sum;
Push_one(h);
}
void Update (int l , int r , int h)
{
if (tree[h].is1)
return ;
if (tree[h].lson == tree[h].rson)
{
tree[h].sum = sqrt(tree[h].sum);
if (tree[h].sum == 1)
tree[h].is1 = true;
return ;
}
int mid = (tree[h].lson + tree[h].rson ) >> 1;
if (r <= mid)
Update (l , r , h << 1 );
else if (l > mid)
Update (l , r , h << 1 | 1);
else
{
Update ( l , mid , h << 1);
Update ( mid + 1 , r , h << 1 | 1);
}
tree[h].sum = tree[h << 1].sum + tree[h << 1 | 1].sum;
Push_one(h);
}
long long Query (int l , int r , int h)
{
if (l == tree[h].lson && r == tree[h].rson)
{
return tree[h].sum;
}
int mid = (tree[h].lson + tree[h].rson) >> 1;
if (mid < l)
Query (l , r , h << 1 | 1);
else if(mid >= r)
Query (l , r , h << 1);
else
return Query (l , mid , h << 1) + Query (mid +1 , r , h << 1 | 1);
}
int main()
{
int n;
int test = 1;
while (~scanf ("%d" , &n))
{
memset (tree , 0 , sizeof (tree));
for (int i = 1 ; i <= n ; i++)
scanf ("%lld" , &num[i]);
Build (1 , n , 1);
int m;
scanf ("%d" , &m);
int a , b , c;
printf ("Case #%d:\n" , test);
test++;
while (m--)
{
scanf ("%d%d%d" , &a , &b , &c);
if(b > c)
swap(b , c);
if (a)
printf ("%lld\n" , Query (b , c , 1));
else
Update (b , c , 1);
}
printf("\n");
}
return 0 ;
}