DS
DS
前言
把所有学过的ds整合一下,不然太难受惹qwq
Part1-树状数组
#define lowbit(x) (x&-x)
int n,m,c[N],a;
void add(int x,int k){
while(x<=N){
c[x]+=k;
x+=lowbit(x);
}
}
int sum(int x){
int res=0;
while(x){
res+=c[x];
x-=lowbit(x);
}
return res;
}
Part2-ST表
void pre(){
longn[1]=0;
longn[2]=1;
for(int i=3;i<maxn;i++)
longn[i]=longn[i/2]+1;
}
int main(){
int n=read(),m=read();
for(int i=1;i<=n;i++)
d[i][0]=read();
pre();
for(int j=1;j<=logn;j++)
for(int i=1;i+(1<<j)-1<=n;i++)
d[i][j]=max(d[i][j-1],d[i+(1<<(j-1))][j-1]);
for(int i=1;i<=m;i++){
int x=read(),y=read();
int s=longn[y-x+1];
printf("%d\n",max(d[x][s],d[y-(1<<s)+1][s]));
}
return 0;
}
Part3-线段树
朴素
#define ls (p<<1)
#define rs (p<<1|1)
ll a[MAX], sum[MAX * 4], ch[MAX * 4], laz[MAX * 4];
void get(int p) {
sum[p] = (sum[ls] + sum[rs]) % mod;
}
void pushdown (int s, int t, int p) {
int mid = s + ((t - s) >> 1);
if (ch[p] != 1) {
ch[ls] *= ch[p], ch[ls] %= mod;
ch[rs] *= ch[p], ch[rs] %= mod;
laz[ls] *= ch[p], laz[ls] %= mod;
laz[rs] *= ch[p], laz[rs] %= mod;
sum[ls] *= ch[p], sum[ls] %= mod;
sum[rs] *= ch[p], sum[rs] %= mod;
ch[p] = 1;
}
if (laz[p]) {
sum[ls] += laz[p] * (mid - s + 1), sum[ls] %= mod;
sum[rs] += laz[p] * (t - mid), sum[rs] %= mod;
laz[ls] += laz[p], laz[ls] %= mod;
laz[rs] += laz[p], laz[rs] %= mod;
laz[p] = 0;
}
return;
}
//建树
void build(int s,int t,int p){
ch[p] = 1;
if (s == t) {
sum[p] = a[s];
return;
}
int mid = (s + ((t - s) >> 1));
build(s ,mid ,ls);
build(mid + 1 ,t , rs);
get(p);
return;
}
//区间乘
void by(int l, int r, ll b, int s, int t, int p){
int mid = s + ((t - s) >> 1);
if (l <= s && t <= r) {
ch[p] *= b, ch[p] %= mod;
laz[p] *= b, laz[p] %= mod;
sum[p] *= b, sum[p] %= mod;
return;
}
pushdown(s, t, p);
if (l <= mid ) by(l, r, b, s, mid, ls) ;
if (r > mid ) by(l, r, b, mid + 1, t, rs) ;
get(p);
return;
}
//区间修改 +
void add(int l,int r,int c,int s,int t,int p){
int mid = s + ((t - s) >> 1);
if (l <= s && t <= r){
sum[p] += 1ll * (t - s + 1) * c, sum[p] %= mod;
laz[p] += c, laz[p] %= mod;
return ;
}
pushdown(s, t, p);
if (l <= mid) add(l ,r ,c ,s ,mid ,ls);
if (r > mid) add(l ,r ,c ,mid + 1,t ,rs);
get(p);
return;
}
ll getsum(int l,int r,int s,int t,int p){
int mid = s + ((t - s) >> 1);
ll ans = 0;
if (l <= s && r >= t)
return sum[p] % mod;
pushdown(s, t, p);
if (l <= mid) ans += getsum(l ,r ,s ,mid ,ls);
ans %= mod;
if (r > mid) ans += getsum(l ,r ,mid + 1 ,t ,rs);
ans %= mod;
return ans % mod;
}
咳咳,看到之前的码风,差点猝死(
线段树合并+分裂
#define N 200050
#define ll long long
int n,m;
int rt[N],tot,cnt;
int bac[N<<5],ct;
void Del(int y){
bac[++ct]=y;
t[y].ls=t[y].rs=t[y].v=0;
}
int New(){
return ct?bac[ct--]:++tot;
}
void pushup(int p){
t[p].v=t[t[p].ls].v+t[t[p].rs].v;
}
int merge(int a,int b,int l,int r){
if(!a||!b){
return a|=b;
}
if(l==r){
t[a].v+=t[b].v;
return a;
}
int mid=l+r>>1;
t[a].ls=merge(t[a].ls,t[b].ls,l,mid);
t[a].rs=merge(t[a].rs,t[b].rs,mid+1,r);
pushup(a);
Del(b);
return a;
}
int split(int a,int b,ll k){
if(!a)return a;
b=New();
ll v=t[t[a].ls].v;
if(v<k)t[b].rs=split(t[a].rs,t[b].rs,k-v);
else std::swap(t[a].rs,t[b].rs);
if(v>k)t[b].ls=split(t[a].ls,t[b].ls,k);
t[b].v=t[a].v-k;
t[a].v=k;
return b;
}
int kth(int p,int l,int r,int k){//一般分裂用来求第k小
if(l==r)return l;
int mid=l+r>>1;
if(k<=t[t[p].ls].v)return kth(t[p].ls,l,mid,k);
else return kth(t[p].rs,mid+1,r,k-t[t[p].ls].v);
}
这才是狼狼的码风,上面是权值树嗷。
可持久化线段树
#define N 1000005
int n,m,tot,len;
int a[N],b[N],rt[N];
int sum[N<<5],ls[N<<5],rs[N<<5];
int build(int l,int r){
int root=++tot;
sum[root]=0;
if(l==r)return root;
int mid=(l+r)>>1;
ls[root]=build(l,mid);
rs[root]=build(mid+1,r);
return root;
}
int update(int k,int l,int r,int root){//root上个版本
int x=++tot;
ls[x]=ls[root],rs[x]=rs[root],sum[x]=sum[root]+1;
if(l==r)return x;
int mid=(l+r)>>1;
if(k<=mid){
ls[x]=update(k,l,mid,ls[x]);
}
else{
rs[x]=update(k,mid+1,r,rs[x]);
}
return x;
}
int query(int u,int v,int l,int r,int k){//(u,v)第k小
int x=sum[ls[v]]-sum[ls[u]];
int mid=(l+r)>>1;
if(l==r)return l;
if(k<=x){
return query(ls[u],ls[v],l,mid,k);
}
else return query(rs[u],rs[v],mid+1,r,k-x);
}
下面是可持久化并查集
#define N 200050
#define ls t[p].lson
#define rs t[p].rson
#define v t[p].val
#define fa t[p].f
#define mid (l+r>>1)
#define max(x,y) (x>y?x:y)
int n,m,rt[N],tot;
struct segtree{
int val,f,lson,rson;
}t[N*50];
int build(int l,int r){
int p=++tot;
if(l==r){
v=1;fa=l;return p;
}
ls=build(l,mid);
rs=build(mid+1,r);
return p;
}
int query_fa(int p,int l,int r,int pos){
if(l==r)return fa;
if(pos<=mid)return query_fa(ls,l,mid,pos);
else return query_fa(rs,mid+1,r,pos);
}
int query_rk(int p,int l,int r,int pos){
if(l==r)return v;
if(pos<=mid)return query_rk(ls,l,mid,pos);
else return query_rk(rs,mid+1,r,pos);
}
int upd_val(int now,int l,int r,int pos,int vv){
int p=++tot;
t[p]=t[now];
if(l==r){
v=max(v,vv);return p;
}
if(pos<=mid)ls=upd_val(t[now].lson,l,mid,pos,vv);
else rs=upd_val(t[now].rson,mid+1,r,pos,vv);
return p;
}
int upd_fa(int now,int l,int r,int pos,int f){
int p=++tot;
t[p]=t[now];
if(l==r){
fa=f;return p;
}
if(pos<=mid)ls=upd_fa(t[now].lson,l,mid,pos,f);
else rs=upd_fa(t[now].rson,mid+1,r,pos,f);
return p;
}
int find(int p,int pos){
int f=query_fa(p,1,n,pos);
if(f==pos)return f;
else return find(p,f);
}
李超线段树
#define N 201005
#define eps 1e-9
#define ls p<<1
#define rs p<<1|1
#define mid (l+r>>1)
#define pdi pair<double,int>
#define f first
#define s second
#define mod 39989
#define mod1 1000000000
using std::pair;
struct line {
double k,b;
}l[N];
int s[N],cnt,n,lastans,x,xx,y,yy,op;
int cmp(double x,double y){//x>y
if(x-y>eps)return 1;
if(y-x>eps)return -1;
return 0;
}
double cale(int id,int x){//计算值
return l[id].b+l[id].k*x;
}
void add(int x,int y,int xx,int yy){//加入直线
cnt++;
if(x==xx){
l[cnt].k=0;l[cnt].b=std::max(y,yy);
}
else {
l[cnt].k=1.0*(yy-y)/(xx-x);l[cnt].b=1.0*(yy-xx*l[cnt].k);
}
}
void upd(int p,int l,int r,int u){
int&v=s[p];
if(cmp(cale(u,mid),cale(v,mid))==1)std::swap(u,v);
int bl=cmp(cale(u,l),cale(v,l)),br=cmp(cale(u,r),cale(v,r));
if(bl==1||(!bl&&u<v))upd(ls,l,mid,u);
if(br==1||(!br&&u<v))upd(rs,mid+1,r,u);
}
void update(int p,int l,int r,int x,int y,int k){
if(l>=x&&r<=y){
upd(p,l,r,k);
return;
}
if(x<=mid)update(ls,l,mid,x,y,k);
if(y>mid)update(rs,mid+1,r,x,y,k);
}
pdi pmax(pdi a,pdi b){//比较大小
if(cmp(a.f,b.f)==1){
return a;
}
if(cmp(a.f,b.f)==-1){
return b;
}
return a.s<b.s?a:b;
}
pdi query(int p,int l,int r,int k){//查询 x=k 时的最大y
if(k<l||k>r)return{0,0};
double res=cale(s[p],k);
if(l==r)return {res,s[p]};
return pmax({res,s[p]},pmax(query(ls,l,mid,k),query(rs,mid+1,r,k)));
}
下面是斜率优化用滴
db g(int m,int x){
return (db)(l[m].k*x+l[m].b);
}
void change(int&p,ll l,ll r,int t){
if(!p){
p=++idx;
tr[p].id=t;
}
ll mid=l+r>>1;
if(l==r)return;
if(g(t,mid)<g(tr[p].id,mid))std::swap(t,tr[p].id);
if(g(t,l)<g(tr[p].id,l))change(tr[p].ls,l,mid,t);
else if(g(t,r)<g(tr[p].id,r))change(tr[p].rs,mid+1,r,t);
}
db qry(int p,ll l,ll r){
if(!p)return INF;
if(l==r){
return g(tr[p].id,u);
}
db ret=g(tr[p].id,u);
ll mid=l+r>>1;
return std::min(ret,u<=mid?qry(tr[p].ls,l,mid):qry(tr[p].rs,mid+1,r));
}
简化了不少,还用了动开()
Part4-trie树
朴素
#define N 525500
#define ls ch[x][0]
#define rs ch[x][1]
int ch[N*25][2],rt[N],w[N*25],sum[N*25],cnt;
void maintain(int x){
w[x]=sum[x]=0;
if(ls){
w[x]+=w[ls];
sum[x]^=(sum[ls]<<1);
}
if(rs){
w[x]+=w[rs];
sum[x]^=(sum[rs]<<1)|(w[rs]&1);
}
}
int makenew(){
int x=++cnt;ch[x][0]=ch[x][1]=w[x]=sum[x]=0;
return x;
}
void insert(int&x,int k,int dep){
if(!x)x=makenew();
if(dep>23)return (void)(w[x]++);
insert(ch[x][k&1],k>>1,dep+1);
maintain(x);
}
void addall(int x){
std::swap(ls,rs);
if(ls)addall(ls);
maintain(x);
}
int merge(int x,int y){
if(!x||!y)return x^y;
w[x]+=w[y];
sum[x]^=sum[y];
ls=merge(ls,ch[y][0]);
rs=merge(rs,ch[y][1]);
return x;
}
可持久化01trie
#define N 600050
#define _N N*33
#define ls ch[x][0]
#define rs ch[x][1]
int ver[_N],ch[_N][2],sum[_N],rt[N],cnt;
int n,m,s[N];
void insert(int now,int lst,int k){//这里注意一下ver表示的是哪个版本就OK了
for(int i=28;i>=0;i--){
ver[now]=ver[lst]+1;
int b=(k>>i)&1;
if(!ch[now][b])ch[now][b]=++cnt;
ch[now][!b]=ch[lst][!b];
now=ch[now][b];
lst=ch[lst][b];
}
ver[now]=ver[lst]+1;
}
int qry(int l,int r,int k){//(l,r)求异或k的最大值
int res=0;
for(int i=28;i>=0;i--){
int b=(k>>i)&1;
if(ver[ch[r][!b]]-ver[ch[l][!b]]){//判断区间内有没有
res^=(1<<i);
r=ch[r][!b];l=ch[l][!b];
}
else r=ch[r][b],l=ch[l][b];
}
return res;
}
Part5-平衡树
treap
#define mt make_tuple
#define f first
#define s second
std::mt19937 myrand(0);
using std::pair;
using std::tuple;
using std::make_tuple;
using std::tie;
struct Node{
Node*ch[2];
int val,p,siz,cnt;
Node(Node*node){
val=node->val;p=node->p;siz=node->siz;cnt=node->cnt;
}
Node(int val):val(val),siz(1),cnt(1){
ch[0]=ch[1]=nullptr;
p=myrand();
}
void upd_siz(){
siz=cnt;
if(ch[0]!=nullptr)siz+=ch[0]->siz;
if(ch[1]!=nullptr)siz+=ch[1]->siz;
}
};
struct non_xuan_treap{
Node*root;
pair<Node*,Node*>split(Node*cur,int val){
if(cur==nullptr)return {nullptr,nullptr};
if(cur->val>val){
auto temp=split(cur->ch[0],val);
cur->ch[0]=temp.s;
cur->upd_siz();
return {temp.f,cur};
}
else{
auto temp=split(cur->ch[1],val);
cur->ch[1]=temp.f;
cur->upd_siz();
return {cur,temp.s};
}
}
tuple<Node*,Node*,Node*>split_by_rk(Node*cur,int rk){
if(cur==nullptr)return mt(nullptr,nullptr,nullptr);
int ls=cur->ch[0]==nullptr?0:cur->ch[0]->siz;
if(rk<=ls){
Node*l,*mid,*r;
tie(l,mid,r)=split_by_rk(cur->ch[0],rk);
cur->ch[0]=r;//
cur->upd_siz();
return mt(l,mid,cur);
}
else if(rk<=ls+cur->cnt){
Node*l=cur->ch[0];
Node*r=cur->ch[1];
cur->ch[0]=cur->ch[1]=nullptr;
cur->upd_siz();
return mt(l,cur,r);
}
else{
Node*l,*mid,*r;
tie(l,mid,r)=split_by_rk(cur->ch[1],rk-ls-cur->cnt);
cur->ch[1]=l;//
cur->upd_siz();
return mt(cur,mid,r);
}
}
Node*merge(Node*u,Node*v){
if(u==nullptr&&v==nullptr)return nullptr;
if(u!=nullptr&&v==nullptr)return u;
if(u==nullptr&&v!=nullptr)return v;
if(u->p<v->p){
u->ch[1]=merge(u->ch[1],v);
u->upd_siz();
return u;
}
else{
v->ch[0]=merge(u,v->ch[0]);
v->upd_siz();
return v;
}
}
void insert(int val){
auto temp=split(root,val);
auto ll=split(temp.f,val-1);
Node*new_;
if(ll.s==nullptr){
new_=new Node(val);
}
else{
ll.s->cnt++;
ll.s->upd_siz();
}
auto l=merge(ll.f,ll.s==nullptr?new_:ll.s);
root=merge(l,temp.s);
}
void del(int val){
auto temp=split(root,val);
auto ll=split(temp.f,val-1);
if(ll.s->cnt>1){
ll.s->cnt--;
ll.s->upd_siz();
}
else{
if(temp.f==ll.s){
temp.f=nullptr;//
}
delete ll.s;
ll.s=nullptr;
}
auto l=merge(ll.f,ll.s);
root=merge(l,temp.s);
}
int qrank_by_val(Node*cur,int val){
auto temp=split(cur,val-1);
int ret=(temp.f==nullptr?0:temp.f->siz)+1;
root=merge(temp.f,temp.s);
return ret;
}
int qval_by_rank(Node*cur,int rk){
Node*l,*mid,*r;
tie(l,mid,r)=split_by_rk(cur,rk);
int ret=mid->val;
root=merge(merge(l,mid),r);
return ret;
}
int q_beforeval(int val){
auto temp=split(root,val-1);
int ret=qval_by_rank(temp.f,temp.f->siz);
root=merge(temp.f,temp.s);
return ret;
}
int q_laterval(int val){
auto temp=split(root,val);
int ret=qval_by_rank(temp.s,1);
root=merge(temp.f,temp.s);
return ret;
}
}T;
装逼写的指针xwx
splay
#define N 200006
struct node{
int ch[2];
int siz,val,tag,fa;
void init(int v,int f){
ch[0]=ch[1]=0;
val=v;fa=f;tag=0;siz=1;
}
}s[N];
int root,n,m,tot,l,r;
void pushup(int p){
s[p].siz=s[s[p].ch[0]].siz+s[s[p].ch[1]].siz+1;
}
void pushdown(int p){
if(s[p].tag){
s[s[p].ch[0]].tag^=1;
s[s[p].ch[1]].tag^=1;
s[p].tag=0;
std::swap(s[p].ch[0],s[p].ch[1]);
}
}
void rot(int x){
int y=s[x].fa,z=s[y].fa,k=s[y].ch[1]==x;
if(z)
s[z].ch[s[z].ch[1]==y]=x;
s[x].fa=z;
s[y].ch[k]=s[x].ch[k^1];
s[s[x].ch[k^1]].fa=y;
s[x].ch[k^1]=y;
s[y].fa=x;
pushup(x);pushup(y);
}
void splay(int x,int goal){
while(s[x].fa!=goal){
int y=s[x].fa,z=s[y].fa;
if(z!=goal)
rot((s[y].ch[1]==x)^(s[z].ch[1]==y)?x:y);
rot(x);
}
if(goal==0)root=x;
}
int kth(int k){
int u=root;
while(1){
pushdown(u);
if(k<=s[s[u].ch[0]].siz)u=s[u].ch[0];
else if(s[s[u].ch[0]].siz+1==k)return u;
else k-=s[s[u].ch[0]].siz+1,u=s[u].ch[1];
}
}
void insert(int x){
int u=root,f=0;
while(u)f=u,u=s[u].ch[x>s[f].val];
u=++tot;
if(f)
s[f].ch[x>s[f].val]=u;
s[u].init(x,f);
splay(u,0);
}
Part-6动态树
LCT
#define N 300050
#define ls ch[x][0]
#define rs ch[x][1]
#define isroot(x) (ch[f[x]][0]!=x&&ch[f[x]][1]!=x)
#define get(x) (ch[f[x]][1]==x)
int n,m,ch[N][2],f[N],s[N],v[N],r[N],top,st[N];
void pushup(int x){
s[x]=s[ls]^s[rs]^v[x];
}
void pushr(int x){
std::swap(ls,rs);
r[x]^=1;
}
void pushdown(int x){
if(r[x]){
if(ls)pushr(ls);
if(rs)pushr(rs);
r[x]=0;
}
}
void rotate(int x){
int y=f[x],z=f[y],k=get(x);
if(!isroot(y))ch[z][get(y)]=x;
ch[y][k]=ch[x][!k],f[ch[x][!k]]=y;
ch[x][!k]=y,f[y]=x,f[x]=z;
pushup(y);pushup(x);
}
void splay(int x){
top=1;st[top]=x;
for(int i=x;!isroot(i);i=f[i])st[++top]=f[i];
for(int i=top;i;i--)pushdown(st[i]);
for(int fa;fa=f[x],!isroot(x);rotate(x))
if(!isroot(fa))rotate(get(fa)==get(x)?fa:x);
}
void access(int x){
for(int p=0;x;x=f[p=x])
splay(x),rs=p,pushup(x);
}
void makeroot(int x){
access(x);splay(x);pushr(x);
}
int findroot(int x){
access(x);
splay(x);
while(ls)pushdown(x),x=ls;
splay(x);
return x;
}
void split(int x,int y){
makeroot(x);access(y);splay(y);
}
void link(int x,int y){
makeroot(x);
if(findroot(y)==x)return;
f[x]=y;
}
void cut(int x,int y){
makeroot(x);
if(findroot(y)!=x||f[y]!=x||ch[y][0])return;
f[y]=rs=0;pushup(x);
}

浙公网安备 33010602011771号