-
Notifications
You must be signed in to change notification settings - Fork 1
/
SPOJ-GSS3 - Can you answer these queries III.cpp
165 lines (146 loc) · 4.03 KB
/
SPOJ-GSS3 - Can you answer these queries III.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
/// This can be easily solved by segtree ,but here I use treap
#include<bits/stdc++.h>
using namespace std;
struct node
{
int prior,size;
int val;//value stored in the array
int sum;//whatever info you want to maintain in segtree for each node
int leftbest;
int rightbest;
int ans;
struct node *l,*r;
};
typedef node* pnode;
int sz(pnode t)
{
return t?t->size:0;
}
void upd_sz(pnode t)
{
if(t)t->size=sz(t->l)+1+sz(t->r);
}
void reset(pnode t)
{
if(t)t->sum =t->leftbest=t->rightbest=t->ans=t->val;//no need to reset lazy coz when we call this lazy would itself be propagated
}
/// we are finding maximum contiguous sum inside a range
/// Here we should take into account another some fields
/// leftmost is maximum contiguous sum starting from first element in a range
/// rightmost is maximum contiguous sum which will end at last element of a range
/// when we merge two tree then ,we have to keep these properties
/// new leftbest will be max(l->leftbest,l->sum+r->leftbest)
/// new rightbest will be max(r->rightbest,r->sum+l->rightbest)
/// so,answer will be max (l->rightbest+r->leftbest , l->ans,r->ans)
void combine(pnode& t,pnode l,pnode r) ///combining two ranges of segtree
{
if(!l || !r)return void(t = l?l:r);
t->ans=max(l->rightbest+r->leftbest,max(l->ans,r->ans));
t->leftbest=max(l->leftbest,l->sum+r->leftbest);
t->rightbest=max(r->rightbest,r->sum+l->rightbest);
t->sum = l->sum + r->sum;
}
void operation(pnode t) ///operation of segtree
{
if(!t)return;
reset(t);//reset the value of current node assuming it now represents a single element of the array
// lazy(t->l);
// lazy(t->r);//imp:propagate lazy before combining t->l,t->r;
combine(t,t->l,t);
combine(t,t,t->r);
}
void split(pnode t,pnode &l,pnode &r,int pos,int add=0)
{
if(!t)return void(l=r=NULL);
// lazy(t);
int curr_pos = add + sz(t->l);
if(curr_pos<=pos)//element at pos goes to left subtree(l)
split(t->r,t->r,r,pos,curr_pos+1),l=t;
else
split(t->l,l,t->l,pos,add),r=t;
upd_sz(t);
operation(t);
}
void merge(pnode &t,pnode l,pnode r) //l->leftarray,r->rightarray,t->resulting array
{
// lazy(l);
// lazy(r);
if(!l || !r) t = l?l:r;
else if(l->prior>r->prior)merge(l->r,l->r,r),t=l;
else merge(r->l,l,r->l),t=r;
upd_sz(t);
operation(t);
}
pnode init(int val)
{
pnode ret = (pnode)malloc(sizeof(node));
ret->l=NULL;
ret->r=NULL;
ret->prior=rand();/// randomly assigned priority value
ret->size=1;
ret->val=val;
ret->sum=val;
ret->leftbest=val;
ret->rightbest=val;
ret->ans=val;
// ret->lazy=0;
return ret;
}
int range_query(pnode t,int l,int r) //[l,r]
{
pnode L,mid,R;
split(t,L,mid,l-1);
split(mid,t,R,r-l);//note: r-l!!
int ans = t->ans;
merge(mid,L,t);
merge(t,mid,R);
return ans;
}
void range_update(pnode t,int l,int r,int val) //[l,r]
{
pnode L,mid,R;
split(t,L,mid,l-1);
split(mid,t,R,r-l);//note: r-l!!
// t->lazy+=val; //lazy_update
merge(mid,L,t);
merge(t,mid,R);
}
int main()
{
/// it will be our main root
pnode root=NULL;
int n;
cin>>n;
for(int i=0;i<n;i++)
{
int a;
cin>>a;
/// adding elements in our root gradually
merge(root,root,init(a));
}
int q,c,x,y;
cin>>q;
while(q--)
{
cin>>c;
/// replace x position's element with y
if(c==0)
{
cin>>x>>y;
x--;
pnode l,r;
split(root,l,r,x-1);/// main->[1...n], l->[1...x-1], r->[x...n]
split(r,r,root,0);/// main->[x...n], r->[x], root[x+1....n]
merge(l,l,init(y));/// merge l->[1....x-1] & [y] ,now l->[1...x] where x position takes new element
merge(root,l,root);/// merge l->[1..x] & root[x+1...n] ,now again root->[1....n]
}
/// range query ,like segment tree
else
{
cin>>x>>y;
x--,y--;
printf("%d\n",range_query(root,x,y));
}
}
return 0;
}