社区讨论
wwgs1145行超级屎山求调,悬赏n关
灌水区参与者 23已保存回复 29
讨论操作
快速查看讨论及其快照的属性,并进行相关操作。
- 当前回复
- 29 条
- 当前快照
- 1 份
- 快照标识符
- @lo2w59s0
- 此快照首次捕获于
- 2023/10/23 20:45 2 年前
- 此快照最后确认于
- 2023/10/23 20:45 2 年前
P3380 二逼平衡树
前面的那一大坨尸不要看(
有超级巨犇能改出来我直接叫全机房的人关注他(
CPP// the beginning of <bits/std++.h>
// C++ includes used for precompiling -*- C++ -*-
// Copyright (C) 2003-2014 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
// terms of the GNU General Public License as published by the
// Free Software Foundation; either version 3, or (at your option)
// any later version.
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// Under Section 7 of GPL version 3, you are granted additional
// permissions described in the GCC Runtime Library Exception, version
// 3.1, as published by the Free Software Foundation.
// You should have received a copy of the GNU General Public License and
// a copy of the GCC Runtime Library Exception along with this program;
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
// <http://www.gnu.org/licenses/>.
/** @file stdc++.h
* This is an implementation file for a precompiled header.
*/
// 17.4.1.2 Headers
// C
#ifndef _GLIBCXX_NO_ASSERT
#include <cassert>
#endif
#include <cctype>
#include <cerrno>
#include <cfloat>
#include <ciso646>
#include <climits>
#include <clocale>
#include <cmath>
#include <csetjmp>
#include <csignal>
#include <cstdarg>
#include <cstddef>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#if __cplusplus >= 201103L
#include <ccomplex>
#include <cfenv>
#include <cinttypes>
#include <cstdalign>
#include <cstdbool>
#include <cstdint>
#include <ctgmath>
#include <cwchar>
#include <cwctype>
#endif
// C++
#include <algorithm>
#include <bitset>
#include <complex>
#include <deque>
#include <exception>
#include <fstream>
#include <functional>
#include <iomanip>
#include <ios>
#include <iosfwd>
#include <iostream>
#include <istream>
#include <iterator>
#include <limits>
#include <list>
#include <locale>
#include <map>
#include <memory>
#include <new>
#include <numeric>
#include <ostream>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <stdexcept>
#include <streambuf>
#include <string>
#include <typeinfo>
#include <utility>
#include <valarray>
#include <vector>
#if __cplusplus >= 201103L
#include <array>
#include <atomic>
#include <chrono>
#include <condition_variable>
#include <forward_list>
#include <future>
#include <initializer_list>
#include <mutex>
#include <random>
#include <ratio>
#include <regex>
#include <scoped_allocator>
#include <system_error>
#include <thread>
#include <tuple>
#include <typeindex>
#include <type_traits>
#include <unordered_map>
#include <unordered_set>
#endif
// the end of <bits/std++.h>
//the begining of "OILib.h"
/*
定义了部分简便的类型缩写
包含一部分基础数据结构
*/
namespace OILib{
#if __cplusplus <= 199711L
#error too old compiler bruh
#endif
typedef long long llong ;
typedef long double exdouble;
typedef unsigned int uint;
typedef unsigned long long ullong;
template<typename T>
using Function=std::function<T>;
template<typename Type,uint offset=0>
class Array{
private:
uint size;
Type *arr;
inline void ReMalloc(const uint newSize){
Type*p=new Type[newSize]();
if(arr!=nullptr)delete[]arr;
arr=p;
size=newSize;
}
inline void ReMalloc(const uint newSize,const Type&val){
ReMalloc(newSize);
for(uint i=0;i<size;i++)arr[i]=val;
}
public:
Array():size(0),arr(nullptr){}
Array(const uint size):size(0),arr(nullptr)
{ReMalloc(size);}
Array(const uint size,const Type&val):size(0),arr(nullptr)
{ReMalloc(size,val);}
Array(const Array&obj):size(0),arr(nullptr)
{
if(this==&obj)return;
ReMalloc(obj.size);
for(uint i=0;i<size;i++)arr[i]=obj.arr[i];
}
Array(const std::initializer_list<Type>&li):size(0),arr(nullptr){
ReMalloc(li.size());
uint i=0;
for(
typename std::initializer_list<Type>::iterator it=li.begin();
it!=li.end();
it++,i++
)arr[i]=(*it);
}
Array(const std::vector<Type>&v):size(0),arr(nullptr){
ReMalloc(v.size());
for(uint i=0;i<size;i++)arr[i]=v[i];
}
Array(const Type*newArr,const int newSize):size(0),arr(nullptr){
ReMalloc(newSize);
for(uint i=0;i<size;i++)arr[i]=newArr[i];
}
Array(const uint size,std::istream&stream):size(0),arr(nullptr){
ReMalloc(size);
stream>>(*this);
}
// Array(const uint size,Freader&reader):size(0),arr(nullptr){
// ReMalloc(size);
// for(uint i=0;i<size;i++)reader>>reader[i];
// }
Array&operator=(const Array&obj){
if(this==&obj)return *this;
ReMalloc(obj.size);
for(uint i=0;i<size;i++)arr[i]=obj.arr[i];
return *this;
}
~Array(){
size=0;
if(arr!=nullptr)delete[]arr;
arr=nullptr;
}
bool operator==(const Array&obj)const{
if(this==&obj)return true;
if(size!=obj.size)return false;
for(uint i=0;i<size;i++)
if(!(arr[i]==obj[i]))
return false;
return true;
}
void ReSize(const uint newSize){
Array newArr(newSize);
for(uint i=0;i<std::min(newSize,size);i++)newArr[i]=arr[i];
(*this)=newArr;
}
inline Type&operator[](const uint index){return arr[index-offset];}
inline const Type&operator[](const uint index)const{return arr[index-offset];}
inline uint GetSize()const{return size;}
inline uint GetOffset()const{return offset;}
friend class Iterator;
class Iterator:public std::iterator<std::random_access_iterator_tag,Type>{
friend class Array;
Type *p;
public:
Iterator():p(nullptr){}
Iterator(const Iterator&obj):p(obj.p){}
~Iterator(){}
Iterator&operator=(const Iterator&obj){p=obj.p;return *this;}
Type&operator*()const{return *p;}
Iterator&operator++(){p++;return *this;}
Iterator&operator--(){p--;return *this;}
Iterator operator++(int){Iterator it(*this);p++;return it;}
Iterator operator--(int){Iterator it(*this);p--;return it;}
Iterator&operator+=(const uint i){p+=i;return *this;}
Iterator&operator-=(const uint i){p-=i;return *this;}
Iterator operator+(const uint i)const{Iterator it(*this);it.p+=i;return it;}
Iterator operator-(const uint i)const{Iterator it(*this);it.p-=i;return it;}
uint operator-(const Iterator&obj)const{return (uint)(p>obj.p?p-obj.p:obj.p-p);}
bool operator!=(const Iterator&obj)const{return p!=obj.p;}
bool operator==(const Iterator&obj)const{return p==obj.p;}
bool operator<(const Iterator&obj)const{return p<obj.p;}
bool operator>(const Iterator&obj)const{return p>obj.p;}
bool operator<=(const Iterator&obj)const{return p<=obj.p;}
bool operator>=(const Iterator&obj)const{return p>=obj.p;}
};
friend class ConstIterator;
class ConstIterator:public std::iterator<std::random_access_iterator_tag,Type>{
friend class Array;
Type *p;
public:
ConstIterator():p(nullptr){}
ConstIterator(const Iterator&obj):p(obj.p){}
~ConstIterator(){}
ConstIterator&operator=(const Iterator&obj){p=obj.p;return *this;}
const Type&operator*()const{return *p;}
ConstIterator&operator++(){p++;return *this;}
ConstIterator&operator--(){p--;return *this;}
ConstIterator operator++(int){ConstIterator it(*this);p++;return it;}
ConstIterator operator--(int){ConstIterator it(*this);p--;return it;}
ConstIterator&operator+=(const uint i){p+=i;return *this;}
ConstIterator&operator-=(const uint i){p-=i;return *this;}
ConstIterator operator+(const uint i)const{ConstIterator it(*this);it.p+=i;return it;}
ConstIterator operator-(const uint i)const{ConstIterator it(*this);it.p-=i;return it;}
uint operator-(const ConstIterator&obj)const{return (uint)(p>obj.p?p-obj.p:obj.p-p);}
bool operator!=(const ConstIterator&obj)const{return p!=obj.p;}
bool operator==(const ConstIterator&obj)const{return p==obj.p;}
bool operator<(const ConstIterator&obj)const{return p<obj.p;}
bool operator>(const ConstIterator&obj)const{return p>obj.p;}
bool operator<=(const ConstIterator&obj)const{return p<=obj.p;}
bool operator>=(const ConstIterator&obj)const{return p>=obj.p;}
};
Iterator Begin(){Iterator it;it.p=&arr[0];return it;}
Iterator End(){Iterator it;it.p=&arr[size-1]+1;return it;}
inline Iterator begin(){return Begin();}
inline Iterator end(){return End();}
ConstIterator Begin()const{ConstIterator it;it.p=&arr[0];return it;}
ConstIterator End()const{ConstIterator it;it.p=&arr[size-1]+1;return it;}
inline ConstIterator begin()const{return Begin();}
inline ConstIterator end()const{return End();}
friend std::istream&operator>>(std::istream&stream,Array&arr){
for(auto&val:arr)stream>>val;
return stream;
}
friend std::ostream&operator<<(std::ostream&stream,const Array&arr){
for(auto&val:arr)stream<<val<<' ';
return stream;
}
};
template<typename Type>
class List{
private:
struct Node{
Node():val(Type()),pre(nullptr),next(nullptr){}
Node(const Type&val):val(val),pre(nullptr),next(nullptr){}
~Node(){
if(pre!=nullptr)pre->next=next;
if(next!=nullptr)next->pre=pre;
val=Type();
pre=nullptr;next=nullptr;
}
Type val;
Node *pre,*next;
};
uint length;
Node *head,*tail;
Node* InsertBack(Node*p,const Type&val){
Node *newNode=new Node(val);
if(p==nullptr){
if(head==nullptr){
head=tail=newNode;
}else{
newNode->next=head;
head->pre=newNode;
head=newNode;
}
}else{
if(p==tail){
p->next=newNode;
newNode->pre=p;
tail=newNode;
}else{
Node *pre=p,*next=p->next;
pre->next=newNode;
newNode->pre=pre;
newNode->next=next;
next->pre=newNode;
}
}
length++;
return newNode;
}
Node* InsertFront(Node *p,const Type&val){
if(p==nullptr)return InsertBack(tail,val);
return InsertBack(p->pre,val);
}
void Erase(Node*p){
if(p==head&&p==tail)head=tail=nullptr;
else if(p==head)head=p->next;
else if(p==tail)tail=p->pre;
length--;
delete p;
}
public:
List():length(0),head(nullptr),tail(nullptr){}
List(const Array<Type>&arr):length(0),head(nullptr),tail(nullptr)
{
for(
typename Array<Type>::ConstIterator it=arr.Begin();
it!=arr.End();
it++
)InsertBack(tail,*it);
}
~List(){while(length)Erase(head);}
friend class Iterator;
class Iterator:public std::iterator<std::bidirectional_iterator_tag,Type>
{
friend class List;
Node *p;
public:
Iterator():p(nullptr){}
Iterator(const Iterator&obj):p(obj.p){}
~Iterator(){}
Iterator&operator=(const Iterator&obj){p=obj.p;return *this;}
Type&operator*()const{return p->val;}
Iterator&operator++(){p=p->next;return *this;}
Iterator&operator--(){p=p->pre;return *this;}
Iterator operator++(int){Iterator it(*this);p=p->next;return it;}
Iterator operator--(int){Iterator it(*this);p=p->pre;return it;}
bool operator!=(const Iterator&obj)const{return p!=obj.p;}
bool operator==(const Iterator&obj)const{return p==obj.p;}
};
friend class ConstIterator;
class ConstIterator:public std::iterator<std::bidirectional_iterator_tag,Type>
{
friend class List;
Node *p;
public:
ConstIterator():p(nullptr){}
ConstIterator(const ConstIterator&obj):p(obj.p){}
~ConstIterator(){}
ConstIterator&operator=(const ConstIterator&obj){p=obj.p;return *this;}
const Type&operator*()const{return p->val;}
ConstIterator&operator++(){p=p->next;return *this;}
ConstIterator&operator--(){p=p->pre;return *this;}
ConstIterator operator++(int){ConstIterator it(*this);p=p->next;return it;}
ConstIterator operator--(int){ConstIterator it(*this);p=p->pre;return it;}
bool operator!=(const ConstIterator&obj)const{return p!=obj.p;}
bool operator==(const ConstIterator&obj)const{return p==obj.p;}
};
private:
Iterator MakeIterator(Node*p){Iterator it;it.p=p;return it;}
ConstIterator MakeIterator(Node*p)const{ConstIterator it;it.p=p;return it;}
public:
inline Iterator Begin(){return MakeIterator(head);}
inline Iterator End(){return MakeIterator(nullptr);}
inline Iterator begin(){return Begin();}
inline Iterator end(){return End();}
inline ConstIterator Begin()const{return MakeIterator(head);}
inline ConstIterator End()const{return MakeIterator(nullptr);}
inline ConstIterator begin()const{return Begin();}
inline ConstIterator end()const{return End();}
inline Iterator InsertFront(Iterator it,const Type&val){return MakeIterator(InsertFront(it.p,val));}
inline Iterator InsertBack(Iterator it,const Type&val){return MakeIterator(InsertBack(it.p,val));}
inline Iterator PushFront(const Type&val){return MakeIterator(InsertFront(head,val));}
inline Iterator PushBack(const Type&val){return MakeIterator(InsertBack(tail,val));}
inline void Erase(const Iterator&it){Erase(it.p);}
};
template<typename Val,uint offset=0>
class Graph{
private:
Array<List<std::pair<uint,Val> >,offset>edge;
public:
Graph(){}
Graph(const uint size):edge(Array<List<std::pair<uint,Val> >,offset>(size)){}
void ReSize(const uint newSize){edge.ReSize(newSize);}
void AddEdge(const uint u,const uint v){edge[u].PushBack(std::make_pair(v,Val()));}
void AddEdge(const uint u,const uint v,const Val&val){edge[u].PushBack(std::make_pair(v,val));}
List<std::pair<uint,Val> >&Edge(const uint u){return edge[u];}
const List<std::pair<uint,Val> >&GetEdge(const uint u)const{return edge[u];}
};
template<uint offset>
class Graph<void,offset>{
private:
Array<List<uint>,offset>edge;
public:
Graph(){}
Graph(const uint size):edge(Array<List<uint>,0>(size)){}
void ReSize(const uint newSize){edge.ReSize(newSize);}
void AddEdge(const uint u,const uint v){edge[u].PushBack(v);}
List<uint>&Edge(const uint u){return edge[u];}
const List<uint>&GetEdge(const uint u)const{return edge[u];}
};
template<typename Type>
class SparseTable{
private:
Function<Type(Type,Type)>Func;
Array<Array<std::pair<Type,Type> > >f;
void MakeTable(const Array<Type>&arr){
f.ReSize(std::log2(arr.GetSize())+1);
f[0].ReSize(arr.GetSize());
for(uint i=0;i<arr.GetSize();i++)f[0][i]=std::make_pair(arr[i],i);
for(uint j=1;(1u<<j)<=arr.GetSize();j++){
f[j].ReSize(arr.GetSize()-(1<<j)+1);
for(uint i=0;i<arr.GetSize()-(1<<j)+1;i++){
if(Func(f[j-1][i].first,f[j-1][i+(1<<(j-1))].first)==f[j-1][i].first)
f[j][i]=std::make_pair(f[j-1][i].first,f[j-1][i].second);
else
f[j][i]=std::make_pair(f[j-1][i+(1<<(j-1))].first,f[j-1][i+(1<<(j-1))].second);
}
}
}
public:
SparseTable(){}
SparseTable(const SparseTable&obj):Func(obj.Func),f(obj.f){}
SparseTable(const Array<Type>&arr,const Function<Type(Type,Type)>&Func):Func(Func)
{MakeTable(arr);}
uint RMQ(const uint l,const uint r)const{
uint len=log2(r-l+1);
if(Func(f[len][l].first,f[len][r-(1<<len)+1].first)==f[len][l].first){
return f[len][l].second;
}else{
return f[len][r-(1<<len)+1].second;
}
}
};
template<typename Type,uint offset=0>
class Discretizationer{
private:
std::unordered_map<Type,uint>m;
std::unordered_map<uint,Type>rm;
public:
Discretizationer(){}
Discretizationer(const Array<Type>&arr){Discretization(arr);}
void Discretization(Array<Type>arr){
m.clear();rm.clear();
sort(arr.Begin(),arr.End());
for(const Type&val:arr)
if(m.find(val)==m.end())
rm[m[val]=m.size()-1u+offset]=val;
}
uint IndexMax()const{return m.size();}
uint GetIndex(const Type&val)const{return *(m.find(val));}
Type Object(const uint ind)const{return *(rm.find(ind));}
const Type& GetObject(const uint ind)const{return *(rm.find(ind));}
};
// template<typename Type,typename Tag>
// class Trie{
// private:
// struct Node{
// Node(){}
// Node(const Type&val):val(val){}
// ~Node(){
// val=Type();
// tag=Tag();
// for(auto it=child.begin();it!=child.end();it++)
// delete (*it).second;
// child.clear();
// }
// Type val;
// Tag tag;
// std::unordered_map<Type,Node*>child;
//
// Node* Malloc(const Type&val){
// if(child[val]==nullptr)child[val]=new Node(val);
// return child[val];
// }
// Node* GetChild(const Type&val){return child[val];}
// const Node* GetChild(const Type&val)const{return child[val];}
// };
// std::vector<Node*>perRoot;
// public:
// Trie(){perRoot.push_back(new Node());}
// void Insert(const Array<Type>&arr,const Tag&tag,const uint ver=0){
// Node *u=perRoot[ver];
// for(auto it=arr.Begin();it!=arr.End();it++)
// u=u->Malloc(*it);
// u->tag+=tag;
// }
// uint PerInsert(const Array<Type>&arr,const Tag&tag,const uint ver=0){
// Node *u=perRoot[ver];
// for(auto it=arr.Begin();it!=arr.End();it++)
// u=u->Malloc(*it);
// u->tag+=tag;
// }
// };
template<typename Type>
class Range{
public:
Type l,r;
Range(){}
Range(const Type&l,const Type&r):l(l),r(r){}
private:
friend class Iterator;
class IteratorBase:public std::iterator<std::bidirectional_iterator_tag,Type>
{
protected:
friend class Range;
Type now;
public:
IteratorBase(){}
IteratorBase(const IteratorBase&obj):now(obj.now){}
~IteratorBase(){}
IteratorBase&operator=(const IteratorBase&obj){now=obj.now;return *this;}
IteratorBase&operator++(){now++;return *this;}
IteratorBase&operator--(){now--;return *this;}
IteratorBase operator++(int){IteratorBase it(*this);now++;return it;}
IteratorBase operator--(int){IteratorBase it(*this);now--;return it;}
bool operator!=(const IteratorBase&obj)const{return now!=obj.now;}
bool operator==(const IteratorBase&obj)const{return now==obj.now;}
};
public:
class Iterator:public IteratorBase{public:Type&operator*(){return this->now;}};
class ConstIterator:public IteratorBase{public:const Type&operator*()const{return this->now;}};
private:
Iterator MakeIterator(const Type&val){Iterator it;it.now=val;return it;}
ConstIterator MakeIterator(const Type&val)const{ConstIterator it;it.now=val;return it;}
public:
inline Iterator Begin(){return MakeIterator(l);}
inline Iterator End(){Type temp=r;return MakeIterator(++temp);}
inline Iterator begin(){return Begin();}
inline Iterator end(){return End();}
inline ConstIterator Begin()const{return MakeIterator(l);}
inline ConstIterator End()const{Type temp=r;return MakeIterator(++temp);}
inline ConstIterator begin()const{return Begin();}
inline ConstIterator end()const{return End();}
};
template<typename Type>
Range<Type>MakeRange(const Type&l,const Type&r){return Range<Type>(l,r);}
template<typename Integer>
Array<bool>GetBits(Integer val){
constexpr uint length=sizeof(Integer)*8;
std::bitset<length>bitSet(val);
Array<bool>bits(length);
for(uint i=0;i<length;i++)bits[i]=bitSet[length-1-i];
return bits;
}
}
namespace OILib{
const int Max=100000;
const int Mod=1e9;
}
//the end of "OILib.h"
using namespace std;
using namespace OILib;
template<typename Type>
class SegmentTree_OnlyReturnNode{
private:
struct Node{
Node():lc(nullptr),rc(nullptr){}
Node(const llong l,const llong r):l(l),r(r),lc(nullptr),rc(nullptr),val(Type()){}
~Node(){
if(lc!=nullptr)delete lc;
if(rc!=nullptr)delete rc;
}
llong l,r;
Node *lc,*rc;
Type val;
inline llong GetMiddle(){return (l+r)/2;}
}*root;
Node* NewNode(const llong l,const llong r){return new Node(l,r);}
Node* CopyNode(Node *p){
Node *newP=new Node();
(*newP)=(*p);
return newP;
}
Node* CreateLeft(Node *p){
if(p->lc==nullptr){
llong l=p->l,r=p->r;
p->lc=NewNode(l,(l+r)/2);
}
return p->lc;
}
Node* CreateRight(Node *p){
if(p->rc==nullptr){
llong l=p->l,r=p->r;
p->rc=NewNode((l+r)/2+1,r);
}
return p->rc;
}
void Create(Node *p){
CreateLeft(p);
CreateRight(p);
}
std::vector<Type*>Query(Node *p,const llong pos){
if(pos<(p->l)||(p->r)<pos)return std::vector<Type*>();
std::vector<Type*>v;
v.push_back(&(p->val));
if(p->l==p->r)return v;
if(pos<=p->GetMiddle()){
auto v2=Query(CreateLeft(p),pos);
v.insert(v.end(),v2.begin(),v2.end());
}else{
auto v2=Query(CreateRight(p),pos);
v.insert(v.end(),v2.begin(),v2.end());
}
return v;
}
std::vector<Type*> Query(Node *p,const llong l,const llong r){
if(r<(p->l)||(p->r)<l)return vector<Type*>();
std::vector<Type*>v,v1,v2;
//cout<<p->l<<','<<p->r<<'\n';
if(l<=(p->l)&&(p->r)<=r){
v.push_back(&(p->val));
return v;
}
v1=Query(p->lc,l,r);
v2=Query(p->rc,l,r);
v.insert(v.end(),v1.begin(),v1.end());
v.insert(v.end(),v2.begin(),v2.end());
return v;
}
public:
SegmentTree_OnlyReturnNode():root(nullptr){}
SegmentTree_OnlyReturnNode(const int l,const int r):root(new Node(l,r)){}
~SegmentTree_OnlyReturnNode(){if(root!=nullptr)delete root;}
std::vector<Type*> Query(const llong pos){return Query(root,pos);}
std::vector<Type*> Query(const llong l,const llong r){return Query(root,l,r);}
};
template<typename Type>
class AVLTree{
private:
struct Node{
Node():prt(nullptr),lc(nullptr),rc(nullptr),size(1),cnt(1),val(Type()){}
Node(const Type&val):prt(nullptr),lc(nullptr),rc(nullptr),size(1),cnt(1),val(val){}
Node *prt,*lc,*rc;
uint size;
uint cnt;
Type val;
}*root;
void PushUp(Node *x){
x->size=x->cnt;
if(x->lc!=nullptr)x->size+=x->lc->size;
if(x->rc!=nullptr)x->size+=x->rc->size;
}
void Zig(Node *x){
Node *y=x->prt;
if(y==nullptr)return;
Node *prt=y->prt;
Node *t1=x->lc,*t2=x->rc,*t3=y->rc;
if(t1!=nullptr)t1->prt=x;
if(t2!=nullptr)t2->prt=y;
if(t3!=nullptr)t3->prt=y;
x->lc=t1,x->rc=y,x->prt=prt;
y->lc=t2,y->rc=t3,y->prt=x;
if(prt!=nullptr){
if(prt->lc==y)
prt->lc=x;
else
prt->rc=x;
}
PushUp(x);PushUp(y);
if(prt!=nullptr)PushUp(prt);
}
void Zag(Node *y){
Node *x=y->prt;
if(x==nullptr)return;
Node *prt=x->prt;
Node *t1=x->lc,*t2=y->lc,*t3=y->rc;
if(t1!=nullptr)t1->prt=x;
if(t2!=nullptr)t2->prt=x;
if(t3!=nullptr)t3->prt=y;
x->lc=t1,x->rc=t2,x->prt=y;
y->lc=x,y->rc=t3,y->prt=prt;
if(prt!=nullptr){
if(prt->lc==x)
prt->lc=y;
else
prt->rc=y;
}
PushUp(x);PushUp(y);
if(prt!=nullptr)PushUp(prt);
}
void Rotate(Node *p){
if(p->prt->lc==p)Zig(p);
else Zag(p);
}
Node* Splay(Node *p){
while(p->prt!=nullptr){
if(p->prt->prt==nullptr){
Rotate(p);
}else{
if(p->prt->lc==p){
if(p->prt->prt->lc==p->prt){
Rotate(p->prt);Rotate(p);
}else{
Rotate(p);Rotate(p);
}
}else{
if(p->prt->prt->lc==p->prt){
Rotate(p);Rotate(p);
}else{
Rotate(p->prt);Rotate(p);
}
}
}
}
return p;
}
Node* Find(const Type&val){
Node *now=root;
while(now!=nullptr){
if(val<now->val){
now=now->lc;
}else if(val==now->val){
return root=Splay(now);
}else{
now=now->rc;
}
}
return now;
}
Node* FindMax(Node*root){
Node *now=root;
while(now->rc!=nullptr)now=now->rc;
return Splay(now);
}
Node* FindMin(Node*root){
Node *now=root;
while(now->lc!=nullptr)now=now->lc;
return Splay(now);
}
public:
AVLTree():root(nullptr){}
void Insert(const Type&val){
if(root==nullptr){
root=new Node(val);
return;
}
Node *p=Find(val);
if(p!=nullptr){
p->cnt++;
p->size++;
return;
}
Node *now=root;
while(true){
if(val<=now->val){
if(now->lc==nullptr)break;
now=now->lc;
}else{
if(now->rc==nullptr)break;
now=now->rc;
}
}
if(val<now->val){
now->lc=new Node(val);
now->lc->prt=now;
PushUp(now);
root=Splay(now->lc);
}else{
now->rc=new Node(val);
now->rc->prt=now;
PushUp(now);
root=Splay(now->rc);
}
}
void Delete(const Type&val){
Node *p=Find(val);
root=Splay(p);
p->cnt--;
if(p->cnt>0)return;
if(p->lc==nullptr&&p->rc==nullptr){
root=nullptr;
}else if(p->lc==nullptr){
p->rc->prt=nullptr;
root=p->rc;
}else if(p->rc==nullptr){
p->lc->prt=nullptr;
root=p->lc;
}else{
p->lc->prt=nullptr;
p->rc->prt=nullptr;
Node *pl=FindMax(p->lc);
pl->rc=p->rc;
p->rc->prt=pl;
root=pl;
PushUp(pl);
}
delete p;
}
bool IsExist(const Type&val){
if(Find(val)==nullptr)return false;
return true;
}
uint CountRank(const Type&val){
Node *now=root;
uint ans=0;
while(now!=nullptr){
if(val<now->val){
now=now->lc;
}else if(val==now->val){
root=Splay(now);
if(now->lc==nullptr)return 1;
else return now->lc->size+1;
}else{
if(now->lc==nullptr)ans+=now->cnt;
else ans+=now->lc->size+now->cnt;
now=now->rc;
}
}
return ans+1;
}
Type FindKth(uint rank){
Node *now=root;
while(now!=nullptr){
if(rank<=(now->lc==nullptr?0:now->lc->size)){
now=now->lc;
}else if(rank<=(now->lc==nullptr?0:now->lc->size)+now->cnt){
root=Splay(now);
return now->val;
}else{
rank-=(now->lc==nullptr?0:now->lc->size)+now->cnt;
now=now->rc;
}
}
return Type();
}
Type FindPre(const Type&val){
Insert(val);
Node *p=Find(val);
if(p->lc==nullptr)return INT_MIN;
p=p->lc;
while(p->rc!=nullptr)p=p->rc;
Delete(val);
return p->val;
}
Type FindSuc(const Type&val){
Insert(val);
Node *p=Find(val);
if(p->rc==nullptr)return INT_MAX;
p=p->rc;
while(p->lc!=nullptr)p=p->lc;
Delete(val);
return p->val;
}
Type FindMax(){
Node *now=root;
while(now->rc!=nullptr)now=now->rc;
return now->val;
}
Type FindMin(){
Node *now=root;
while(now->lc!=nullptr)now=now->lc;
return now->val;
}
uint GetSize(){return root->sum;}
};
bool CountIsExist(const vector<AVLTree<int>*>&v,const int k){
for(auto pt:v)
if((*pt).IsExist(k))
return true;
return false;
}
int CountRank(const vector<AVLTree<int>*>&v,const int k){
int ans=0;
for(auto pt:v)
ans+=(*pt).CountRank(k)-1;
return ans+1;
}
int CountMax(const vector<AVLTree<int>*>&v){
int ans=INT_MIN;
for(auto pt:v)
ans=max(ans,(*pt).FindMax());
return ans;
}
int CountMin(const vector<AVLTree<int>*>&v){
int ans=INT_MAX;
for(auto pt:v)
ans=min(ans,(*pt).FindMin());
return ans;
}
int CountKth(const vector<AVLTree<int>*>&v,const int k){
int l=CountMin(v),r=CountMax(v),mid;
while(l<r){
mid=(l+r+1)/2;
if(k<CountRank(v,mid))r=mid-1;
else if(k<CountRank(v,mid+1)){
return mid;
}else l=mid;
}
return l;
}
template<size_t bufSize>
class Freader{
public:
Freader():lp(buf),rp(buf){}
char GetChar(){
if(lp==rp){
lp=buf;
rp=lp+fread(buf,sizeof(char),bufSize,stdin);
if(lp==rp)return EOF;
}
return *lp++;
}
friend Freader&operator>>(Freader&reader,char&obj){
obj=reader.GetChar();
while((!IsLawful(obj))&&(obj!=EOF))
obj=reader.GetChar();
return reader;
}
friend Freader&operator>>(Freader&reader,int&obj){
obj=0;
bool isNega=false;
char c=reader.GetChar();
while((!IsDigit(c))&&(c!=EOF)){
if(c=='-')isNega=true;
c=reader.GetChar();
}
while((IsDigit(c))&&(c!=EOF)){
obj=(obj*10)+(int)(c-'0');
c=reader.GetChar();
}
if(isNega)obj=-obj;
return reader;
}
friend Freader&operator>>(Freader&reader,llong&obj){
obj=0;
bool isNega=false;
char c=reader.GetChar();
while((!IsDigit(c))&&(c!=EOF)){
if(c=='-')isNega=true;
c=reader.GetChar();
}
while((IsDigit(c))&&(c!=EOF)){
obj=(obj*10)+(int)(c-'0');
c=reader.GetChar();
}
return reader;
}
friend Freader&operator>>(Freader&reader,uint&obj){
obj=0;
char c=reader.GetChar();
while((!IsDigit(c))&&(c!=EOF))c=reader.GetChar();
while((IsDigit(c))&&(c!=EOF)){
obj=(obj*10)+(int)(c-'0');
c=reader.GetChar();
}
return reader;
}
friend Freader&operator>>(Freader&reader,ullong&obj){
obj=0;
char c=reader.GetChar();
while((!IsDigit(c))&&(c!=EOF))c=reader.GetChar();
while((IsDigit(c))&&(c!=EOF)){
obj=(obj*10)+(int)(c-'0');
c=reader.GetChar();
}
return reader;
}
friend Freader&operator>>(Freader&reader,string&obj){
char c=reader.GetChar();
obj=string();
while(IsLawful(c)&&(c!=EOF)){
obj+=c;
c=reader.GetChar();
}
return reader;
}
private:
static bool IsLawful(const char c){
if(c==' '||c=='\n'||c=='\r')return false;
return true;
}
static bool IsDigit(const char c){
if('0'<=c&&c<='9')return true;
return false;
}
char buf[bufSize];
char *lp,*rp;
};
Freader<1<<20>Fin;
template<size_t bufSize>
class Fwriter{
public:
Fwriter():p(buf){}
~Fwriter(){Flush();}
void PutChar(const char c){
*(p++)=c;
if(p>=buf+bufSize)Flush();
}
friend Fwriter&operator<<(Fwriter&writer,const char obj){
writer.PutChar(obj);
return writer;
}
friend Fwriter&operator<<(Fwriter&writer,const int obj){
int now=abs(obj);
string s;
while(now>0){
s+=(now%10)+'0';
now/=10;
}
if(obj<0)writer.PutChar('-');
for(int i=s.length()-1;i>=0;i--)
writer.PutChar(s[i]);
return writer;
}
friend Fwriter&operator<<(Fwriter&writer,const string obj){
for(size_t i=0;i<obj.length();i++)
writer.PutChar(obj[i]);
return writer;
}
private:
void Flush(){
fwrite(buf,p-buf,1,stdout);
p=buf;
}
char buf[bufSize];
char *p;
};
Fwriter<1<<20>Fout;
#define cin Fin
#define cout Fout
void Solve(){
int n,m;
cin>>n>>m;
SegmentTree_OnlyReturnNode<AVLTree<int> >tree(1,n);
Array<int,1>arr(n);
for(auto i:MakeRange(1,n)){
cin>>arr[i];
vector<AVLTree<int>*>v=tree.Query(i);
for(auto pt:v)(*pt).Insert(arr[i]);
}
for(auto i:MakeRange(1,m)){
int opt;
cin>>opt;
if(opt==1){
int l,r,k;
cin>>l>>r>>k;
int ans=0;
vector<AVLTree<int>*>v=tree.Query(l,r);
for(auto pt:v)
ans+=(*pt).CountRank(k)-1;
cout<<ans+1<<'\n';
}else if(opt==2){
int l,r,k;
cin>>l>>r>>k;
cout<<CountKth(tree.Query(l,r),k)<<'\n';
}else if(opt==3){
int pos,k;
cin>>pos>>k;
int bef=arr[pos];
arr[pos]=k;
vector<AVLTree<int>*>v=tree.Query(pos);
for(auto pt:v){
(*pt).Delete(bef);
(*pt).Insert(k);
}
}else if(opt==4){
int l,r,k;
cin>>l>>r>>k;
vector<AVLTree<int>*>v=tree.Query(l,r);
int ans=INT_MIN;
for(auto pt:v)ans=max(ans,(*pt).FindPre(k));
cout<<ans<<'\n';
}else if(opt==5){
int l,r,k;
cin>>l>>r>>k;
vector<AVLTree<int>*>v=tree.Query(l,r);
int ans=INT_MAX;
for(auto pt:v)ans=min(ans,(*pt).FindSuc(k));
cout<<ans<<'\n';
}
}
}
int main(){
// freopen("P3380_1.in","r",stdin);
// freopen("P3380_1.ans","w",stdout);
// ios::sync_with_stdio(false);
// cin.tie(0);cout.tie(0);
Solve();
return 0;
}
回复
共 29 条回复,欢迎继续交流。
正在加载回复...