hello all .. i m trying to the problem http://www.spoj.com/problems/HORRIBLE/ but getting wa again n again... i have used segment trees with lazy propgation .. i have also solved similar problem http://www.spoj.com/problems/LITE/ but i couldnt understand y m gettin wa in this
here is my code....
#include<cstdio>
#define MAX 300000
typedef long long LL;
LL n,m;
struct tree{
LL add;
LL total;
}T[MAX];
void update(LL Node,LL left,LL right,LL i,LL j,LL v){
if(i==left && j==right){
T[Node].add += v;
T[Node].total += (j-i+1)*v;
return;
}
LL mid=(left + right)>>1, L = Node<<1 , R = L+1;
if(j<=mid)update(L,left,mid,i,j,v);
else if(i>mid)update(R,mid+1,right,i,j,v);
else{
update(L,left,mid,i,mid,v);
update(R,mid+1,right,mid+1,j,v);
}
T[Node].total = T[L].total + T[R].total + T[Node].add*(right-left+1);
}
LL query(LL Node,LL left,LL right,LL i,LL j,LL v){
if(i==left && j==right)return T[Node].total + v*(j-i+1);
LL mid=(left + right)>>1, L = Node <<1 , R = L+1;
if(j<=mid) return query(L,left,mid,i,j,v+T[Node].add);
else if(i>mid)return query(R,mid+1,right,i,j,v+T[Node].add);
else{
LL ret =0;
ret+= query(L,left,mid,i,mid,v+T[Node].add);
ret+= query(R,mid+1,right,mid+1,j,v+T[Node].add);
return ret;
}
}
int main(){
LL t;
scanf("%lld",&t);
while(t--){
scanf("%lld %lld",&n,&m);
for(LL i=0;i<=3*n;i++)
T[i].total = T[i].add = 0;
while(m--){
LL q,a,b,k;
scanf("%lld %lld %lld",&q,&a,&b);
switch(q){
case 0:scanf("%lld",&k);
update(1,0,n-1,a-1,b-1,k);break;
case 1:printf("%lld\n",query(1,0,n-1,a-1,b-1,0));break;
}
}
}
return 0;
}
checked on these test cases :
2
8 6
0 2 4 26
0 4 8 80
0 4 5 20
1 8 8
0 5 7 14
1 4 8
4 3
0 1 4 1
1 2 2
1 1
o/p
80
508
1
3
as provided in question :P
Looks like you got WA because of the %lld modifier. It's very unreliable. I replaced it with %I64d and now you get TLE, which is the same I got when I tried to solve the problem...
Alright.
After learning about lazy propagation, which is new to me, re-coding most of my routines and extensively debugging my code, I managed to get AC with a total runtime of over 8 seconds. Yeah, terribly slow, though it's mainly because of the use of iostream (I couldn't get it accepted using stdio (it's terribly unreliable when it comes to 64-bit integers)).
The first error I see in your code is in the update routine. You have if(i==left && j==right){...}. If the case is that i < left, and then you go to the left child, you call update with parameters L, left, mid, i, mid, v. So i will still be < left, and that subroutine will be skipped. I would replace the logic behind that routine to always let static the values of i and j, and when left >= i && right <= j, update the values of the node and return. And if at any time, left > j || right < i, return.
The same applies to the query routine.
I also changed the update of T[Node].total. As I understood it, lazy propagation works as follows:
I also changed the left and right values of the node. In your code, you dynamically assigned ranges to nodes, and built your tree with a random value of 10^5 * 3. It's always better to build a tree with size 2^x. That way, you'll know that every node has 2 children, and that the range of the first node will be 1 — size / 2.
With those modifications, and a little debugging, your code got accepted too.
Here's the modified version...
Thanks for explanation, it is very helpful. I have one doubt, in update routine you used
T[Node].total += v*(min(right, j)-max(left, i)+1)
how does it work? and why not usedT[Node].total = T[L].total + T[R].total
?What it does is increase the total value of the interval by v * (num of elements in interval). The number of elements is min(right, j) — max(left, i) + 1.
And about the other question, consider this case...
In the first update, the program sets the total variable of the range 1 - 16 to 160. The sub-ranges 1 - 8 and 9 - 16 don't get updated, so they still contain zero. In the second update, the program sets the total variable of the range 1 - 8 to 40 (note that the lazy propagation is done in the queries, but not in the updates), but the range 9 - 16 still contains zero, because it hasn't been lazily updated yet. So if you try to update the range 1 - 16 by doing
T[Node].total = T[L].total + T[R].total
, you would end up with 40 instead of the wanted 200.Furthermore, even if you do the lazy propagation in the update routine as well, in the second update you would set the total variable of the range 1 - 8 to 80 and then increase it by 40, ending up with 120, but the range 9 - 16 will still contain zero, because it's outside the update range. So you will get 120 in 1 - 16 if you do
T[Node].total = T[L].total + T[R].total
, still not the correct result.A way to speed this up is to use scanf. Only the output can overflow. Input can be regular int.
So only that one cout at the end is slow.
Getting WA, anyone can help out?
I am trying to solve the same problem, using optimized version of ST + LP.
I have tried so many test cases, with boundary cases, all are giving correct answer, I am still getting WA though:
Below is my code, any hint?
Here's my solution using your approach, Hope it helps, though it's too late....