- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我们有一个数组 A,有 N 个元素和 N 个范围,每个范围都是 [L, R] 的形式。将范围的值称为 A 中从索引 L 到索引 R(含)的所有元素的总和。
示例:让数组 A = [2 5 7 9 8] 并且给定的范围是 [2,4] 那么这个范围的值是 5+7+9=21
现在我们有 Q 个查询,每个查询都是 2 种类型之一:
1. 0 X Y : It means change Xth element of array to Y.
2. 1 A B : It means we need to report the sum of values of ranges from A to B.
示例:让数组 A = [2 3 7 8 6 5] 并让我们有 3 个范围:
R1: [1,3] Then value corresponding to this range is 2+3+7=12
R2: [4,5] Then value corresponding to this range is 8+6=14
R3: [3,6] Then value corresponding to this range is 7+8+6+5=26
现在让我们有 3 个查询:
Q1: 1 1 2
Then here answer is value of Range1 + value of Range2 = 12+14=26
Q2: 0 2 5
It means Change 2nd element to 5 from 3.It will change the result of Range 1.
Now value of Range1 becomes 2+5+7=14
Q3: 1 1 2
Then here answer is value of Range1 + value of Range2 = 14+14=28
如果我们有 10^5 个查询并且 N 也达到 10^5,该怎么做。如何高效地向 Queries2 报告?
我的方法: 第一个查询很容易处理。我可以从数组构建一个线段树。我可以用它来计算第一个数组(第二个数组中的一个元素)中一个区间的总和。但是我如何处理 O(log n) 中的第二个查询?在最坏的情况下,我更新的元素将在第二个数组中的所有间隔中。
我需要一个 O(Qlog N) 或 O(Q(logN)^2) 的解决方案。
显然我们不能为每个查询设置 O(N)。所以请帮助获得有效的方法
我当前的代码:
#include<bits/stdc++.h>
using namespace std;
long long arr[100002],i,n,Li[100002],Ri[100002],q,j;
long long queries[100002][2],query_val[100002],F[100002],temp;
long long ans[100002];
int main()
{
scanf("%lld",&n);
for(i=1;i<=n;i++)
scanf("%lld",&arr[i]);
for(i=1;i<=n;i++)
{
scanf("%lld%lld",&Li[i],&Ri[i]);
}
for(i=1;i<=n;i++)
{
F[n] = 0;
ans[i] = 0;
}
scanf("%lld",&q);
for(i=1;i<=q;i++)
{
scanf("%lld",&query_val[i]);
scanf("%lld%lld",&queries[i][0],&queries[i][1]);
}
for(i=1;i<=n;i++)
{
for(j=Li[i];j<=Ri[i];j++)
{
F[i] = F[i] + arr[j];
}
}
long long diff;
long long ans_count = 0,k=1;
for(i=1;i<=q;i++)
{
if(query_val[i] == 1)
{
temp = arr[queries[i][0]];
arr[queries[i][0]] = queries[i][1];
diff = arr[queries[i][0]] - temp;
for(j=1;j<=n;j++)
{
if(queries[i][0]>=Li[j] && queries[i][0]<=Ri[j])
F[j] = F[j] + diff;
++k;
}
}
else if(query_val[i] == 2)
{
++ans_count;
for(j=queries[i][0];j<=queries[i][1];j++)
ans[ans_count] = ans[ans_count] + F[j];
}
}
for(i=1;i<=ans_count;i++)
{
printf("%lld\n",ans[i]);
}
return 0;
}
虽然代码是正确的,但是对于更大的测试用例,它需要很长时间。请帮助
最佳答案
#include <iostream>
using namespace std;
typedef long long ll;
void updateSegementLazyTree(ll *tree , ll *lazy , ll low, ll high,ll startR ,ll endR ,ll updateValue ,ll treeNode)
{
//before using current node we need to check weather currentnode has any painding updation or not
if (lazy[treeNode]!=0)
{
//update painding updation
tree[treeNode] += (high-low+1)*lazy[treeNode];
//transfer update record to child of current node if child possible
if (low!=high)
{
//that's means child possible
lazy[treeNode*2] += lazy[treeNode]; //append update to left child
lazy[treeNode*2+1] += lazy[treeNode]; //append update to right child
}
lazy[treeNode]=0;//remove lazyness of current node
}
//if our current interval [low,high] is completely outside of the given Interval[startR,endR]
if (startR >high || endR <low || low>high)
{
//then we have to ignore those path of tree
return;
}
//if our current interval is completely inside of given interval
if (low >=startR && high <=endR)
{
//first need to update the current node with their painding updation
tree[treeNode] += (high-low+1)*updateValue;
if (low!=high)
{
//that's means we are at the non-leaf node
lazy[treeNode*2] +=updateValue; //so append lazyness to their left child
lazy[treeNode*2+1] +=updateValue;//append lazyness to their right child
}
return;
}
//partially inside and outside then we have to traverse all sub tree i.e. right subtree and left subtree also
ll mid=(low+high)/2;
updateSegementLazyTree(tree , lazy , low, mid, startR , endR , updateValue , treeNode*2);
updateSegementLazyTree(tree , lazy , mid+1, high, startR , endR , updateValue , treeNode*2+1);
//while poping the function from stack ,we are going to save what i have done....Ok!!!!
//update tree node:-
tree[treeNode] = tree[treeNode*2] + tree[treeNode*2+1]; //left sum+rightsum(after updation)
}
ll getAnswer(ll *tree ,ll * lazy , ll low, ll high ,ll startR,ll endR , ll treeNode)
{
//base case
if (low>high)
{
return 0;
}
//completely outside
if (low >endR || high <startR)
{
return 0;
}
//before using current node we need to check weather currentnode has any painding updation or not
if (lazy[treeNode]!=0)
{
//i.e. if we would have added x value from low to high then total changes for root node will be (high-low+1)*x
tree[treeNode] += (high-low+1)*lazy[treeNode];
if (low!=high)
{
//if we are at non-leaf node
lazy[treeNode*2] += lazy[treeNode]; //append updateion process to left tree
lazy[treeNode*2+1] += lazy[treeNode];//append updation process to right tree
}
lazy[treeNode]=0;
}
//if our current interval is completely inside of given interval
if (low >=startR && high <=endR)
{
return tree[treeNode];
}
//if our current interval is cpartially inside and partially out side of given interval then we need to travers both side left and right too
ll mid=(low+high)/2;
if(startR>mid)
{
//that's means our start is away from mid so we need to treverse in right subtree
return getAnswer( tree , lazy , mid+1, high, startR, endR , treeNode*2+1);
}else if(endR <= mid){
//that's means our end is so far to mid or equal so need to travers in left subtree
return getAnswer( tree , lazy , low, mid, startR, endR , treeNode*2);
}
ll left=getAnswer( tree , lazy , low, mid, startR, endR , treeNode*2); //traverse right
ll right=getAnswer( tree , lazy , mid+1, high, startR, endR , treeNode*2+1); //and left
return (left+right);//for any node total sum=(leftTreeSum+rightTreeSum)
}
int main()
{
int nTestCase;
cin>>nTestCase;
while(nTestCase--)
{
ll n,nQuery;
cin>>n>>nQuery;
ll *tree=new ll[3*n]();
ll *lazy=new ll[3*n]();
while(nQuery--)
{
int choice;
cin>>choice;
if (choice==0)
{
ll startR,endR,updateValue;
cin>>startR>>endR>>updateValue;
//0:- start index , n-1 end index ,1 treeIndex tree is our segment tree and lazy is our lazy segment tree
updateSegementLazyTree(tree , lazy , 0, n-1, startR-1 , endR-1 , updateValue , 1);
// for (int i = 0; i < 3*n; ++i)
// {
// cout<<i<<"\t"<<tree[i]<<"\t"<<lazy[i]<<endl;
// }
}else{
ll startR,endR;
cin>>startR>>endR;
ll answer=getAnswer(tree , lazy , 0, n-1 , startR-1 , endR-1 , 1);
cout<<answer<<endl;
}
}
}
}
updateSegementLazyTree()
采用两个大小为 4*n
的数组,因为长度为 log(n)
的可能节点总数将是 2*2^log(n)
,最多是 4*n
。然后我们还需要interval[startR,endr]
和updateValue
,我们通过recrusion维护。 Tree[treeNode]
表示左右所有元素的和。
示例输入如下:
1
8 6
0 2 4 26
0 4 8 80
0 4 5 20
1 8 8
0 5 7 14
1 4 8
因此对于第一个查询,我们必须将 2-4
更新为 +26。我们没有更新 2-4 之间的所有元素,而是将其存储在惰性树中,每当我们访问树中的任何节点时,我们首先检查该节点是否有任何待处理的更新。如果没有待处理的更新,请完成并将其转移给他们的 child 。
q1:- 0 2 4 26
tree[0,78,78,0,26,52,0,0,0,26]
尝试做树索引;对于左 tree(2*i+1)
和 right(2*i+1)
第一个索引至少为 78,即树的顶部,因此从 [0,n-1]
当前最大值为 78。
tree[treeNode] += (high-low+1)*lazy[treeNode];
如果我们从低索引到高添加 x
那么在整个子数组 i
中添加了 (high-low+1)*x ; -1
因为从 0
开始索引。
然后,在访问树中的任何节点之前,我们懒惰地检查该节点是否有任何待处理的更新。 if (lazy[treeNode]!=0)
如果有,则更新并将 lazy 传递给他们的 child 。对左子树和右子树也继续这样做。
然后我们在 range[startR,endR]
内到达 getAnswer()
正如我之前提到的,我们首先检查每个受影响节点的挂起更新。如果为真则它完成该更新并根据间隔递归调用左右子树。
最后我们得到根节点的leftSubtree
和rightsubtree
的和,将它们相加并返回。
时间复杂度
在更新中,getAnswer()
,在最坏的情况下必须遍历整棵树,即树的高度 O(2*Log N)
。 2*log n
因为这是最坏的情况,我们必须在左右子树中移动,例如对于区间 [0-n-1]
。
对于 k
查询,整体时间复杂度为 O(K*log n)
。
关于c++ - 带点更新的范围总和范围,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26927026/
运行 PostgreSQL(7.4 和 8.x),我认为这是可行的,但现在我遇到了错误。 我可以单独运行查询,它工作得很好,但如果我使用 UNION 或 UNION ALL,它会抛出错误。 这个错误:
我试图为我的应用程序创建一个导航,使用抽屉导航我的 fragment 之一(HomeFragment)有一个 ViewPager,可容纳 3 个 fragment (Bundy Clock、Annou
以我目前正在开发的应用为例: - 它有一个包含多个项目的抽屉导航;现在有两个项目让我感兴趣,我将它们称为 X 和 Y。 X 和 Y 都在单击时显示包含 x 元素或 y 元素列表的 fragment 选
我有一个形状为 (370,275,210) 的 NumPy 数组,我想将其重新整形为 (275,210,370)。我将如何在 Python 中实现这一点? 370是波段数,275是行数,210是图像包
我们如何与被子 UIViewController 阻止的父 UIViewController(具有按钮)交互。显然,触摸事件不会通过子 Nib 。 (启用用户交互) 注意:我正在加载默认和自定义 NI
我是 Jpa 新手,我想执行过程 我的代码如下 private static final String PERSISTENCE_UNIT_NAME = "todos"; private static
与安装了 LAMP 的 GCE 相比,选择与 Google Cloud SQL 链接的 GCE 实例有哪些优势? 我确定 GCE 是可扩展的,但是安装在其上的 mysql 数据库的可扩展性如何? 使用
这个问题在这里已经有了答案: Value receiver vs. pointer receiver (3 个答案) 关闭 3 年前。 我刚接触 golang。只是想了解为 Calc 类型声明的两种
我不小心按了一个快捷键,一个非常漂亮的断线出现在日期上。 有点像 # 23 Jun 2010 -------------------- 有人知道有问题的快捷方式吗?? (我在 mac 上工作!) 在
我正在Scala中编写正则表达式 val regex = "^foo.*$".r 这很好,但是如果我想做 var x = "foo" val regex = s"""^$x.*$""".r 现在我们有
以下 XML 文档在技术上是否相同? James Dean 19 和: James Dean 19 最佳答案 这两个文档在语义上是相同的。在 X
我在对数据帧列表运行稳健的线性回归模型(使用 MASS 库中的 rlm)时遇到问题。 可重现的示例: var1 <- c(1:100) var2 <- var1*var1 df1 <- data.f
好的,我有一个自定义数字键盘,可以在标签(numberField)中将数字显示为 0.00,现在我需要它显示 $0.00。 NSString *digit = sender.currentTitle;
在基于文档的应用程序中,使用 XIB 文件,创建新窗口时其行为是: 根据最后一个事件的位置进行定位和调整大小 window 。 如果最后一个事件窗口仍然可见,则新窗口 窗口应该是级联的,这样它就不会直
我想使用参数进行查询,如下所示: SELECT * FROM MATABLE WHERE MT_ID IN (368134, 181956) 所以我考虑一下 SELECT * FROM MATABLE
我遇到一些性能问题。 我有一个大约有 200 万行的表。 CREATE TABLE [dbo].[M8]( [M8_ID] [int] IDENTITY(1,1) NOT NULL,
我在 jquery 中的按键功能遇到问题。我不知道为什么按键功能不起作用。我已经使用了正确的 key 代码。在我的函数中有 2 个代码,其中包含 2 个事件键,按一个键表示 (+) 代码 107 和(
我想显示音频波形,我得到了此代码,它需要.raw音频输入并显示音频波形,但是当我放入.3gp,.mp3音频时,我得到白噪声,有人可以帮助我如何使其按需与.3gp一起使用使用.3gp音频运行它。 Inp
我无法让 stristr 函数返回真值,我相信这是因为我的搜索中有一个 $ 字符。 当我这样做时: var_dump($nopricecart); 完整的 $nopricecart 值是 $0 ,我得
如果我有这样的循环: for(int i=0;i O(n) 次。所以do some执行了O(n)次。如果做某事是线性时间,那么代码片段的复杂度是O(n^2)。 关于algorithm - 带 If 语
我是一名优秀的程序员,十分优秀!