#include <stdio.h>
#include <iostream>
#include <stdlib.h>
#include <math.h>
#include <stdbool.h>
#include <string.h>
#include <limits.h>
#define LftChild(x) ((x)<<1)
#define RghtChild(x) (((x)<<1)+1)
#define min(a,b) (((a)<(b))?(a):(b))
#define ROOT 1
static const int MAXN = (int)(1e6);
typedef int ElemType;
typedef struct SegTree{
ElemType RawArr[MAXN+1];
ElemType SegArr[(MAXN<<2)+1];
ElemType Tag[(MAXN<<2)+1];
int Cnt[(MAXN<<2)+1];
int N;
int Depth;
}SegTree,*ptrToSegTree;
namespace UpdFncKit{
//更新组件
//维护区间和
void UpdSum(int *SegSumArr,int x)
{
SegSumArr[x]=SegSumArr[LftChild(x)]+SegSumArr[RghtChild(x)];
}
//维护区间最值
void UpdMin(int *SegMinArr,int x)
{
SegMinArr[x] = min(SegMinArr[LftChild(x)],SegMinArr[RghtChild(x)]);
}
//维护区间最值和计数器
void UpdMinWithCnt(int *SegMinArr,int *Cnt,int x)
{
SegMinArr[x] = min(SegMinArr[LftChild(x)],SegMinArr[RghtChild(x)]);
if(SegMinArr[LftChild(x)] == SegMinArr[RghtChild(x)]) Cnt[x]=Cnt[LftChild(x)]+Cnt[RghtChild(x)];
else if(SegMinArr[LftChild(x)] <= SegMinArr[RghtChild(x)])Cnt[x] = Cnt[LftChild(x)];
else Cnt[x] = Cnt[RghtChild(x)];
}
}
namespace MergeFncKit{
//区间查询配套组件
//初始值+合并逻辑
const int INIT_SEG_SUM = 0;
//维护区间和
ElemType MergeSum(ElemType sum_1,ElemType sum_2)
{
return sum_1+sum_2;
}
const int INIT_SEG_MIN = INT_MAX;
const std::pair<ElemType,int> INIT_SEG_MIN_PAIR = {INT_MAX,0};
//维护区间最小值
ElemType MergeMin(ElemType min_1,ElemType min_2)
{
return min(min_1,min_2);
}
//维护区间最小值以及计数器
std::pair<ElemType,int> MergeMinWithCnt(const std::pair<ElemType,int> &p,const std::pair<ElemType ,int> &q)
{
if(p.first == q.first)return {p.first,p.second+q.second};
if(p.first <= q.first)return p;
return q;
}
}
namespace SegmTagDownFncKit{
void SegmSumEqualTagDown(int *SegSumArr,int *Tag,int Lft,int Rght,int Beg,int End,int x,int v)
{
//区间赋值操作
//维护区间和
if(Beg<=Lft && Rght<=End)
{
Tag[x] = v;
SegSumArr[x] = (Rght-Lft+1)*v;
}else if(Tag[x]>0){
int Mid = Lft+((Rght-Lft)>>1);
Tag[LftChild(x)] = Tag[RghtChild(x)] = Tag[x];
Tag[x] = 0;
SegSumArr[LftChild(x)] = (Mid-Lft+1)*Tag[x];
SegSumArr[RghtChild(x)] = (Rght-Mid)*Tag[x];
}
}
void SegmSumPlusTagDown(int *SegSumArr,int *Tag,int Lft,int Rght,int Beg,int End,int x,int v)
{
//区间加操作
//维护区间和
if(Beg<=Lft && Rght<=End)
{
Tag[x] += v;
SegSumArr[x] += (Rght-Lft+1)*v;
}else if(Tag[x]>0){
int Mid = Lft+((Rght-Lft)>>1);
Tag[LftChild(x)] += Tag[x];Tag[RghtChild(x)]+=Tag[x];
Tag[x] = 0;
SegSumArr[LftChild(x)] += (Mid-Lft+1)*Tag[x];
SegSumArr[RghtChild(x)] += (Rght-Mid)*Tag[x];
}
}
void SegmMinPlusTagDown(int *SegMinArr,int *Tag,int Lft,int Rght,int Beg,int End,int x,int v)
{
//区间加操作
//维护最小值
if(Beg<=Lft && Rght<=End)
{
Tag[x] += v;
SegMinArr[x] += (Rght-Lft+1)*v;
}else if(Tag[x]>0){
Tag[LftChild(x)] += Tag[x];Tag[RghtChild(x)]+=Tag[x];
SegMinArr[LftChild(x)] += Tag[x];
SegMinArr[RghtChild(x)] += Tag[x];
Tag[x] = 0;
}
}
}
static void _Build(ptrToSegTree pt,int x,int Lft,int Rght,void(*UPD)(int *SegArr,int x));
static void Build(ptrToSegTree pt,void(*UPD)(int *SegArr,int x))
{
pt->Depth = (int)log(pt->N) + 1;
_Build(pt,ROOT,1,pt->N,UPD);
}
static void _Build(ptrToSegTree pt,int x,int Lft,int Rght,void(*UPD)(int *SegArr,int x))
{
if(Lft == Rght){pt->SegArr[x] = pt->RawArr[x];return;}
int Mid = Lft+((Rght-Lft)>>1);
_Build(pt,LftChild(x),Lft,Mid,UPD);
_Build(pt,RghtChild(x),Mid+1,Rght,UPD);
UPD(pt->SegArr,x);
}
static ElemType _Query(ptrToSegTree pt,
int Beg,int End,int x,int Lft,int Rght,
ElemType(*Merge)(ElemType,ElemType),ElemType INIT,
void(*SegmTagDown)(int *Tag,int *SegArr,int Lft,int Rght,int x,int v)
);
static ElemType Query(ptrToSegTree pt,
int Beg,int End,ElemType(*Merge)(ElemType,ElemType),ElemType INIT,
void(*SegmTagDown)(int *Tag,int *SegArr,int Lft,int Rght,int x,int v))
{
return _Query(pt,Beg,End,ROOT,1,pt->N,Merge,INIT,SegmTagDown);
}
static ElemType _Query(ptrToSegTree pt,
int Beg,int End,int x,int Lft,int Rght,
ElemType(*Merge)(ElemType,ElemType),ElemType INIT,
void(*SegmTagDown)(int *Tag,int *SegArr,int Lft,int Rght,int x,int v))
{
if(Beg<=Lft && Rght <= End)return pt->SegArr[x];
SegmTagDown(pt->Tag,pt->SegArr,Lft,Rght,x,pt->Tag[x]);
int Mid = Lft+((Rght-Lft)>>1);
ElemType LftVal = INIT,RghtVal = INIT;
if(Beg <= Mid)LftVal = Merge(INIT,LftVal);
if(End > Mid)RghtVal = Merge(INIT,RghtVal);
return Merge(LftVal,RghtVal);
}
static void _SingMod(ptrToSegTree pt,
int p,int v,int Lft,int Rght,int x,
void(*UPD)(int *SegArr,int x));
static void SingMod(ptrToSegTree pt,int p,int v,void(*UPD)(int *SegArr,int x))
{
_SingMod(pt,p,v,1,pt->N,ROOT,UPD);
}
static void _SingMod(ptrToSegTree pt,
int p,int v,int Lft,int Rght,int x,
void(*UPD)(int *SegArr,int x))
{
if(Lft == Rght){pt->SegArr[x] = v;return;}
int Mid = Lft+((Rght-Lft)>>1);
if(p<=Mid)_SingMod(pt,p,v,Lft,Mid,LftChild(x),UPD);
else _SingMod(pt,p,v,Mid+1,Rght,RghtChild(x),UPD);
UPD(pt->SegArr,x);
}
static void _SectMod(ptrToSegTree pt,
int Beg,int End,int Lft,int Rght,int v,int x,
void(*SegmTagDown)(int *Tag,int *SegArr,int Lft,int Rght,int Beg,int End,int x,int v),
void(*UPD)(int *SegArr,int x));
static void SectMod(ptrToSegTree pt,
int Beg,int End,int v,
void(*SegmTagDown)(int *SegArr,int *Tag,int Lft,int Rght,int Beg,int End,int x,int v),
void(*UPD)(int *SegArr,int x))
{
_SectMod(pt,Beg,End,1,pt->N,v,ROOT,SegmTagDown,UPD);
}
static void _SectMod(ptrToSegTree pt,
int Beg,int End,int Lft,int Rght,int v,int x,
void(*SegmTagDown)(int *SegArr,int *Tag,int Lft,int Rght,int Beg,int End,int x,int v),
void(*UPD)(int *SegArr,int x))
{
SegmTagDown(pt->SegArr,pt->Tag,Lft,Rght,Beg,End,x,v);
if(Beg<=Lft && End <= Rght)return;
int Mid = Lft+((Rght-Lft)>>1);
if(Beg <= Mid)
_SectMod(pt,Beg,End,Lft,Mid,v,LftChild(x),SegmTagDown,UPD);
if(End>Mid)
_SectMod(pt,Beg,End,Mid+1,Rght,v,RghtChild(x),SegmTagDown,UPD);
UPD(pt->SegArr,x);
}
static std::pair<ElemType,int> _QueryMinWithCnt(ptrToSegTree pt,
int Beg,int End,int Lft,int Rght,int x,
const std::pair<ElemType,int> &INIT,
std::pair<ElemType,int> MergeMinWithCnt(const std::pair<ElemType,int> &p,const std::pair<ElemType ,int> &q),
void(*SegmTagDown)(int *Tag,int *SegArr,int Lft,int Rght,int x,int v)
);
static std::pair<ElemType,int> QueryMinWithCnt(ptrToSegTree pt,
int Beg,int End,
const std::pair<ElemType,int> &INIT,
std::pair<ElemType,int> MergeMinWithCnt(const std::pair<ElemType,int> &p,const std::pair<ElemType ,int> &q),
void(*SegmTagDown)(int *Tag,int *SegArr,int Lft,int Rght,int x,int v))
{
std::pair<ElemType,int> retp = _QueryMinWithCnt(pt,Beg,End,1,pt->N,ROOT,INIT,MergeMinWithCnt,SegmTagDown);
return retp;
}
static std::pair<ElemType,int> _QueryMinWithCnt(ptrToSegTree pt,
int Beg,int End,int Lft,int Rght,int x,
const std::pair<ElemType,int> &INIT,
std::pair<ElemType,int> MergeMinWithCnt(const std::pair<ElemType,int> &p,const std::pair<ElemType ,int> &q),
void(*SegmTagDown)(int *Tag,int *SegArr,int Lft,int Rght,int x,int v)
)
{
if(Beg <= Lft && Rght >= End)return {pt->SegArr[x],pt->Cnt[x]};
SegmTagDown(pt->Tag,pt->SegArr,Lft,Rght,x,pt->Tag[x]);
int Mid = Lft+((Rght-Lft)>>1);
std::pair<ElemType,int> LftPair = MergeMinWithCnt(INIT,_QueryMinWithCnt(pt,Beg,End,Lft,Mid,LftChild(x),INIT,MergeMinWithCnt,SegmTagDown));
std::pair<ElemType,int> RghtPair = MergeMinWithCnt(INIT,_QueryMinWithCnt(pt,Beg,End,Mid+1,Rght,RghtChild(x),INIT,MergeMinWithCnt,SegmTagDown));
return MergeMinWithCnt(LftPair,RghtPair);
}