#import "html_elements.typ": post
#import "./lib.typ": flex, svg_inline
#show: post
- #link(
"https://olimpiada.ic.unicamp.br/pratique/ps/2018/f3/baldes/",
)[Enunciado]
Na minha primeira leitura, vi que esta é uma questão clássica de segtree. Um vetor de tamanho #svg_inline[$10^5$] e #svg_inline[$10^5$] queries dentro desse intervalo. Iremos fazer uma segtree para o mínimo num intervalo e outra para o máximo, sendo a resposta da query em um intervalo o max-min. Para simplificar isso, podemos guardar as duas árvores apenas em um vetor de pairs.
Porém após implementar a primeira solução e não funcionar fiz uma segunda leitura e percebi que o max e o min não podem estar no mesmo balde (na mesma posição no vetor). Então troquei o pair por uma struct, para guardar de qual balde o max e o min vieram. Quando o min e o max estiverem no mesmo balde temos uma certeza, um dos dois faz parte da solução. Nesse caso podemos testar, o query sem o min, mas com o max e o query sem o max, mas com o min.
```cpp
#include
typedef struct ii {
int first;
int second;
int i;
int j;
} ii;
using namespace std;
const int MAX = 5e5+50;
const int inf = 0x3f3f3f3f;
ii tree[MAX]={};
int arr[MAX];
ii merge(ii a, ii b) {
ii c = {min(a.first,b.first),max(a.second,b.second),-1,-2};
if(c.first==a.first) c.i=a.i;
else c.i=b.i;
if(c.second==a.second) c.j=a.j;
else c.j=b.j;
return c;
}
void build(int pos, int i, int j) {
if(i==j) {
tree[pos]={arr[i],arr[i],i,i};
if(arr[i]==0) {
tree[pos]={inf,-inf,-1,-2};
}
} else {
build(2*pos,i,(i+j)/2);
build(2*pos+1,(i+j)/2+1,j);
tree[pos]=merge(tree[2*pos],tree[2*pos+1]);
}
}
void update(int pos, int i, int j, int target, ii val) {
if(i==j) {
if(tree[pos].first!=0&&tree[pos].second!=0) {
tree[pos]=merge(tree[pos],val);
} else {
tree[pos]=val;
}
} else {
if(target <= (i+j)/2) update(2*pos,i,(i+j)/2,target,val);
else update(2*pos+1,(i+j)/2+1,j,target,val);
tree[pos]=merge(tree[2*pos],tree[2*pos+1]);
}
}
void force_update(int pos, int i, int j, int target, ii val) {
if(i==j) {
tree[pos]=val;
} else {
if(target <= (i+j)/2) force_update(2*pos,i,(i+j)/2,target,val);
else force_update(2*pos+1,(i+j)/2+1,j,target,val);
tree[pos]=merge(tree[2*pos],tree[2*pos+1]);
}
}
ii query(int pos, int i, int j, int a, int b) {
if(i>b||j=a&&j<=b) {
return tree[pos];
} else {
return merge(query(2*pos,i,(i+j)/2,a,b),query(2*pos+1,(i+j)/2+1,j,a,b));
}
}
int main() {
int n,m;
scanf("%d%d",&n,&m);
for(int i=0;i