-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathSPOJ QMAX3VN - Giá trị lớn nhất 3.cpp
144 lines (127 loc) · 3.32 KB
/
SPOJ QMAX3VN - Giá trị lớn nhất 3.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
/// Time-360ms
#include<bits/stdc++.h>
using namespace std;
struct node
{
int prior,siz;
int val;//value stored in the array
//whatever info you want to maintain in segtree for each node
int ans;
struct node *l,*r;
};
typedef node* pnode;
int sz(pnode t)
{
return t?t->siz:0;
}
void upd_sz(pnode t)
{
if(t)t->siz=sz(t->l)+1+sz(t->r);
}
void reset(pnode t)
{
if(t) 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->ans,r->ans);
}
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->siz=1;
ret->ans=val;
ret->val=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;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
/// it will be our main root
pnode root=NULL,t=NULL;
int q,c,x,y;
cin>>q;
bool first_time=true;
while(q--)
{
char ch;
cin>>ch;
/// putting element(y) into x position i.e. between ( x-1 and x )
if(ch=='A')
{
cin>>y>>x;
x--;
if(first_time) {t=init(y);root=t;first_time=false;}
else
{
pnode l,r;
split(root,l,r,x-1);
merge(root,l,init(y));
merge(root,root,r);
}
}
/// range query ,like segment tree
else
{
cin>>x>>y;
x--,y--;
cout<<range_query(root,x,y)<<'\n';
}
}
}