树状数组区间求和P3374
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=5e5+10;
int n,m;
struct BIT
{
int lim,tre[N];
inline int lowbit(int x){return x&(-x);}
inline void insert(int x,int val){for(int i=x;i<=lim;i+=lowbit(i))tre[i]+=val;}
inline int query(int x){int temp=0;for(int i=x;i>0;i-=lowbit(i))temp+=tre[i];return temp;}
inline int query(int l,int r){return query(r)-query(l-1);}
}T;
inline int read()
{
int x=0,f=1; char ch=getchar();
while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
return x*f;
}
#undef int
int main()
{
#define int long long
T.lim=n=read(); m=read();
for(int i=1,x;i<=n;i++) x=read(),T.insert(i,x);
for(int i=1,opt,x,y;i<=m;i++)
{
opt=read(); x=read(); y=read();
if(opt==1) T.insert(x,y);
else printf("%lld\n",T.query(x,y));
}
return 0;
}
树状数组区间加P3368
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=5e5+10;
int n,m;
struct BIT
{
int lim,tre[N];
inline int lowbit(int x){return x&(-x);}
inline void insert(int x,int val){for(int i=x;i<=lim;i+=lowbit(i))tre[i]+=val;}
inline void insert(int l,int r,int val){insert(l,val);insert(r+1,-val);}
inline int query(int x){int temp=0;for(int i=x;i>0;i-=lowbit(i))temp+=tre[i];return temp;}
}T;
inline int read()
{
int x=0,f=1; char ch=getchar();
while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
return x*f;
}
#undef int
int main()
{
#define int long long
T.lim=n=read(); m=read();
for(int i=1,x;i<=n;i++) x=read(),T.insert(i,i,x);
for(int i=1,opt,x,y,k;i<=m;i++)
{
opt=read(); x=read();
if(opt==1) y=read(),k=read(),T.insert(x,y,k);
else printf("%lld\n",T.query(x));
}
return 0;
}
线段树区间加P3372
#include<bits/stdc++.h>
#define int long long
#define f() cout<<"Test"<<endl;
#define ls x<<1
#define rs x<<1|1
using namespace std;
inline int read()
{
int x=0,f=1; char ch=getchar();
while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
return x*f;
}
const int N=1e5+10;
struct BIT
{
int tre[N],lim;
inline int lowbit(int x){return x&(-x);}
inline int query(int x){int sum=0;for(int i=x;i;i-=lowbit(i))sum+=tre[i];return sum;}
inline void insert(int x,int val){for(int i=x;i<=lim;i+=lowbit(i))tre[i]+=val;}
inline int query(int l,int r){return query(r)-query(l-1);}
};
struct Segment_Tree
{
struct Node
{
int dat,laz;
}tre[N<<2];
inline void push_up(int x){tre[x].dat=tre[ls].dat+tre[rs].dat;}
inline void push_down(int x,int l,int r)
{
if(!tre[x].laz) return ;
int mid=(l+r)>>1;
tre[ls].dat+=tre[x].laz*(mid-l+1);
tre[rs].dat+=tre[x].laz*(r-mid);
tre[ls].laz+=tre[x].laz;
tre[rs].laz+=tre[x].laz;
tre[x].laz=0;
}
inline void insert(int x,int l,int r,int L,int R,int val)
{
if(L<=l&&r<=R)
{
tre[x].dat+=val*(r-l+1);
tre[x].laz+=val; return ;
}
int mid=(l+r)>>1; push_down(x,l,r);
if(L<=mid) insert(ls,l,mid,L,R,val);
if(R>mid) insert(rs,mid+1,r,L,R,val);
push_up(x);
}
inline int query(int x,int l,int r,int L,int R)
{
if(L<=l&&r<=R) return tre[x].dat;
int mid=(l+r)>>1,sum=0;
push_down(x,l,r);
if(L<=mid) sum+=query(ls,l,mid,L,R);
if(R>mid) sum+=query(rs,mid+1,r,L,R);
push_up(x);
return sum;
}
}T;
int n,m;
#undef int
int main()
{
#define int long long
n=read(); m=read();
for(int i=1,dat;i<=n;i++)
dat=read(),T.insert(1,1,n,i,i,dat);
for(int i=1,opt,x,y,k;i<=m;i++)
{
opt=read(); x=read(); y=read();
if(opt==1) k=read(),T.insert(1,1,n,x,y,k);
else printf("%lld\n",T.query(1,1,n,x,y));
}
return 0;
}
主席树P3834
#include<bits/stdc++.h>
#define int long long
#define f() cout<<"Test"<<endl;
#define ls tre[x].l
#define rs tre[x].r
using namespace std;
inline int read()
{
int x=0,f=1; char ch=getchar();
while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
return x*f;
}
const int N=2e5+10;
int n,m,cnt,all,root[N],s[N],lsh[N];
struct Node
{
int dat,l,r;
}tre[N*20];
void push_up(int x){tre[x].dat=tre[ls].dat+tre[rs].dat;}
int insert(int pre,int l,int r,int pos)
{
int mid=(l+r)>>1,x=++all; tre[x]=tre[pre];
if(l==r) return tre[x].dat++,x;
if(pos<=mid) ls=insert(tre[pre].l,l,mid,pos);
else rs=insert(tre[pre].r,mid+1,r,pos);
push_up(x); return x;
}
int query(int x,int y,int l,int r,int k)
{
if(l==r) return l;
int lsum=tre[tre[y].l].dat-tre[ls].dat,mid=(l+r)>>1;
if(lsum>=k) return query(ls,tre[y].l,l,mid,k);
return query(rs,tre[y].r,mid+1,r,k-lsum);
}
#undef int
int main()
{
#define int long long
n=read(); m=read();
for(int i=1;i<=n;i++)
s[i]=lsh[i]=read();
sort(lsh+1,lsh+n+1);
cnt=unique(lsh+1,lsh+n+1)-lsh-1;
root[0]=++all;
for(int i=1;i<=n;i++)
s[i]=lower_bound(lsh+1,lsh+cnt+1,s[i])-lsh,
root[i]=insert(root[i-1],1,cnt,s[i]);
for(int i=1,l,r,k;i<=m;i++)
{
l=read(); r=read(); k=read();
printf("%lld\n",lsh[query(root[l-1],root[r],1,cnt,k)]);
}
return 0;
}
KMP
#include<bits/stdc++.h>
#define int long long
#define f() cout<<"Test"<<endl;
using namespace std;
inline int read()
{
int x=0,f=1; char ch=getchar();
while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
return x*f;
}
const int N=1e6+10;
int n,m,nxt[N];
char s1[N],s2[N];
#undef int
int main()
{
#define int long long
scanf("%s%s",s1+1,s2+1);
n=strlen(s1+1); m=strlen(s2+1);
for(int i=2,j=0;i<=m;i++)
{
while(j&&s2[j+1]!=s2[i]) j=nxt[j];
j+=(s2[j+1]==s2[i]); nxt[i]=j;
}
for(int i=1,j=0;i<=n;i++)
{
while(j&&s1[i]!=s2[j+1]) j=nxt[j];
j+=(s2[j+1]==s1[i]);
if(j==m) printf("%lld\n",i-m+1);
}
for(int i=1;i<=m;i++) printf("%lld ",nxt[i]);
return 0;
}
分块 (P3202 弹飞绵羊)
#include<bits/stdc++.h>
#define int long long
#define f() cout<<"Test"<<endl;
using namespace std;
inline int read()
{
int x=0,f=1; char ch=getchar();
while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
return x*f;
}
const int N=2e5+10;
int n,cnt,T,pos[N],l[N],r[N],s[N],nxt[N],f[N];
#undef int
inline void deal(int x)
{
for(int i=r[x];i>=l[x];i--)
if(i+s[i]>r[x]) f[i]=1,nxt[i]=i+s[i];
else f[i]=f[i+s[i]]+1,nxt[i]=nxt[i+s[i]];
}
inline int solve(int x){int ans=0;while(x<=n) ans+=f[x],x=nxt[x]; return ans;}
int main()
{
#define int long long
n=read();
for(int i=1;i<=n;i++) s[i]=read();
for(int i=1;i<=sqrt(n);i++) l[i]=(i-1)*sqrt(n)+1,r[i]=i*sqrt(n);
if(r[cnt=sqrt(n)]!=n) l[cnt+1]=r[cnt]+1,r[++cnt]=n;
for(int i=1;i<=cnt;i++) for(int j=l[i];j<=r[i];j++) pos[j]=i;
for(int i=1;i<=cnt;i++) deal(i);
T=read();
while(T--)
{
int opt,p,num; opt=read(); p=read()+1;
if(opt==1) printf("%lld\n",solve(p));
else num=read(),s[p]=num,deal(pos[p]);
}
return 0;
}
AC自动机+拓扑优化 LuoguP5357
#include<bits/stdc++.h>
#define int long long
#define ull unsigned long long
#define f() cout<<"Test: "<<endl
using namespace std;
inline int read()
{
int x=0,f=1; char ch=getchar();
while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
return x*f;
}
const int N=2e6+10,M=2e5+10;
int n,cnt=1,du[N],ans[M];
int tot,head[M],nxt[M],ver[M];
char ch[N];
queue<int> q;
vector<int> v[N];
void add_edge(int x,int y)
{
ver[++tot]=y; nxt[tot]=head[x];
head[x]=tot; du[y]++;
}
struct Trie
{
struct Node
{
int son[26],fail,dat;
}tre[N];
int New(int &x){if(!x) return x=++cnt; return x;}
void insert(char *s,int id)
{
int len=strlen(s),pos=1;
for(int i=0;i<len;i++)
pos=New(tre[pos].son[s[i]-'a']);
v[pos].push_back(id);
}
void get_Fail()
{
for(int i=0;i<26;i++) tre[0].son[i]=1;
q.push(1);
while(!q.empty())
{
int x=q.front(); q.pop();
for(int i=0;i<26;i++)
{
int fail=tre[x].fail,to=tre[x].son[i];
if(!to) tre[x].son[i]=tre[fail].son[i];
else
{
tre[to].fail=tre[fail].son[i];
add_edge(to,tre[fail].son[i]);
q.push(to);
}
}
}
}
void topu()
{
for(int i=1;i<=cnt;i++)
if(!du[i]) q.push(i);
while(!q.empty())
{
int x=q.front(); q.pop();
for(int i=head[x];i;i=nxt[i])
{
int to=ver[i];
tre[to].dat+=tre[x].dat;
if(!(--du[to])) q.push(to);
}
}
}
void query(char *s)
{
int len=strlen(s),pos=1;
for(int i=0;i<len;i++)
{
pos=tre[pos].son[s[i]-'a'];
tre[pos].dat++;
}
topu();
}
}T;
#undef int
int main()
{
#define int long long
n=read();
for(int i=1;i<=n;i++)
scanf("%s",ch),T.insert(ch,i);
scanf("%s",ch); T.get_Fail(); T.query(ch);
for(int i=1;i<=cnt;i++)
for(int j=0;j<v[i].size();j++)
ans[v[i][j]]=T.tre[i].dat;
for(int i=1;i<=n;i++) printf("%lld\n",ans[i]);
return 0;
}
普通平衡树P3369
Splay
#include<bits/stdc++.h>
#define int long long
#define ull unsigned long long
#define f() cout<<"Test: "<<endl
using namespace std;
inline int read()
{
int x=0,f=1; char ch=getchar();
while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
return x*f;
}
const int N=1e5+10;
struct Splay
{
int cnt,root,fa[N],dat[N],rec[N],siz[N],son[N][2];
void clear(int x){fa[x]=dat[x]=rec[x]=siz[x]=son[x][0]=son[x][1]=0;}
int get(int x){return son[fa[x]][1]==x;}
void push_up(int x)
{
if(!x) return ;
siz[x]=rec[x];
if(son[x][0]) siz[x]+=siz[son[x][0]];
if(son[x][1]) siz[x]+=siz[son[x][1]];
}
void connect(int x,int y,int pos)
{
if(x) fa[x]=y;
if(y) son[y][pos]=x;
}
void rotate(int x)
{
int f=fa[x],ff=fa[fa[x]],px=get(x),pf=get(f);
connect(son[x][px^1],f,px);
connect(f,x,px^1);
connect(x,ff,pf);
push_up(f); push_up(x);
}
void splay(int x)
{
for(int f;f=fa[x];rotate(x))
if(fa[f]) rotate(get(x)==get(f)?f:x);
root=x;
}
void insert(int val)
{
if(!root)
{
root=++cnt; dat[root]=val;
siz[root]=rec[root]=1;
son[root][0]=son[root][1]=0;
return ;
}
int x=root,f=0;
while(true)
{
// cout<<"Test\n";
if(dat[x]==val)
{
// cout<<x<<endl;
rec[x]++;
push_up(x); push_up(f);
splay(x); return ;
}
f=x; x=son[x][val>dat[x]];
if(x) continue;
dat[++cnt]=val;
siz[cnt]=rec[cnt]=1;
fa[cnt]=f; son[f][val>dat[f]]=cnt;
push_up(f); splay(cnt); return ;
}
}
int find(int val)//查排名
{
int x=root,temp=0;
while(true)
{
// if(x) cout<<x<<' '<<val<<' '<<dat[x]<<' '<<rec[x]<<endl;
if(val<dat[x]){x=son[x][0];continue;}
temp+=siz[son[x][0]];
if(val==dat[x]) return splay(x),temp+1;
temp+=rec[x]; x=son[x][1];
}
}
int kth(int rk)
{
int x=root;
while(true)
{
if(son[x][0]&&rk<=siz[son[x][0]]){x=son[x][0]; continue;}
if(son[x][0]) rk-=siz[son[x][0]];
if(rk<=rec[x]) return splay(x),dat[x];
rk-=rec[x]; x=son[x][1];
}
}
int ask_pre()
{
int x=son[root][0];
while(son[x][1]) x=son[x][1];
return x;
}
int ask_suf()
{
int x=son[root][1];
while(son[x][0]) x=son[x][0];
return x;
}
void del(int val)
{
find(val);
if(rec[root]>1) return rec[root]--,push_up(root),void();
if(!son[root][0]&&!son[root][1]) return clear(root),root=0,void();
if(!son[root][0])
{
int temp=root;
fa[root=son[root][1]]=0;
clear(temp); return ;
}
if(!son[root][1])
{
int temp=root;
fa[root=son[root][0]]=0;
clear(temp); return ;
}
int temp=root,left=ask_pre();
splay(left); connect(son[temp][1],root,1);
clear(temp); push_up(root);
}
}T;
int n;
#undef int
int main()
{
#define int long long
n=read();
for(int i=1,opt,x;i<=n;i++)
{
opt=read(); x=read();
if(opt==1) T.insert(x);
else if(opt==2) T.del(x);
else if(opt==3) T.insert(x),printf("%lld\n",T.find(x)),T.del(x);
else if(opt==4) printf("%lld\n",T.kth(x));
else if(opt==5) T.insert(x),printf("%lld\n",T.dat[T.ask_pre()]),T.del(x);
else T.insert(x),printf("%lld\n",T.dat[T.ask_suf()]),T.del(x);
}
return 0;
}
FHQ-Treap
#include<bits/stdc++.h>
#define int long long
#define ull unsigned long long
#define f() cout<<"Test: "<<endl
#define ls tre[x].l
#define rs tre[x].r
using namespace std;
inline int read()
{
int x=0,f=1; char ch=getchar();
while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
return x*f;
}
const int N=1e5+10;
struct FHQ_Treap
{
int all,root;
struct Node
{
int l,r,siz,dat,key;
}tre[N];
int New(int val)
{
tre[++all]=(Node){0,0,1,val,rand()};
return all;
}
void push_up(int x){tre[x].siz=tre[ls].siz+tre[rs].siz+1;}
void split(int x,int val,int &u,int &v)
{
if(!x) return u=v=0,void();
if(tre[x].dat<=val) u=x,split(rs,val,rs,v);
else v=x,split(ls,val,u,ls);
push_up(x);
}
int merge(int x,int y)//保证x的值都小于y
{
if(!x||!y) return x+y;
if(tre[x].key>tre[y].key)
return tre[x].r=merge(tre[x].r,y),push_up(x),x;
return tre[y].l=merge(x,tre[y].l),push_up(y),y;
}
void insert(int val)
{
int x=0,y=0; split(root,val,x,y);
root=merge(merge(x,New(val)),y);
}
void del(int val)
{
int x=0,y=0,z=0;
split(root,val,x,z);
split(x,val-1,x,y);
y=merge(tre[y].l,tre[y].r);
root=merge(merge(x,y),z);
}
int find(int val)
{
int x=0,y=0;
split(root,val-1,x,y);
int temp=tre[x].siz+1;
root=merge(x,y);
return temp;
}
int kth(int x,int rk)
{
if(tre[ls].siz+1==rk) return tre[x].dat;
if(tre[ls].siz>=rk) return kth(ls,rk);
return kth(rs,rk-tre[ls].siz-1);
}
int ask_pre(int val)
{
int x=0,y=0;
split(root,val-1,x,y);
int pos=x;
while(tre[pos].r) pos=tre[pos].r;
root=merge(x,y);
return tre[pos].dat;
}
int ask_suf(int val)
{
int x=0,y=0;
split(root,val,x,y);
int pos=y;
while(tre[pos].l) pos=tre[pos].l;
root=merge(x,y);
return tre[pos].dat;
}
}T;
int n;
#undef int
int main()
{
#define int long long
srand(time(0));
n=read();
for(int i=1,opt,x;i<=n;i++)
{
opt=read(); x=read();
if(opt==1) T.insert(x);
else if(opt==2) T.del(x);
else if(opt==3) printf("%lld\n",T.find(x));
else if(opt==4) printf("%lld\n",T.kth(T.root,x));
else if(opt==5) printf("%lld\n",T.ask_pre(x));
else printf("%lld\n",T.ask_suf(x));
}
return 0;
}
P3391 文艺平衡树
FHQ-Treap
#include<bits/stdc++.h>
#define int long long
#define ull unsigned long long
#define f() cout<<"Test: "<<endl
#define ls tre[x].l
#define rs tre[x].r
using namespace std;
inline int read()
{
int x=0,f=1; char ch=getchar();
while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
return x*f;
}
const int N=1e5+10;
struct FHQ_Treap
{
int all,root;
struct Node
{
int l,r,siz,dat,key,laz;
}tre[N];
int New(int val)
{
tre[++all]=(Node){0,0,1,val,rand(),0};
return all;
}
void push_up(int x){tre[x].siz=tre[ls].siz+tre[rs].siz+1;}
void split(int x,int pos,int &u,int &v)
{
if(!x) return u=v=0,void();
push_down(x);
if(pos<=tre[ls].siz) v=x,split(ls,pos,u,ls);
else u=x,split(rs,pos-tre[ls].siz-1,rs,v);
push_up(x);
}
int merge(int x,int y)
{
if(!x||!y) return x+y;
push_down(x); push_down(y);
if(tre[x].key>tre[y].key)
return tre[x].r=merge(tre[x].r,y),push_up(x),x;
return tre[y].l=merge(x,tre[y].l),push_up(y),y;
}
void push_down(int x)
{
if(!x||!tre[x].laz) return ;
tre[x].laz=0; swap(ls,rs);
if(ls) tre[ls].laz^=1;
if(rs) tre[rs].laz^=1;
}
void reverse(int l,int r)
{
int x=0,y=0,z=0;
split(root,r,x,z);
split(x,l-1,x,y);
tre[y].laz^=1;
root=merge(merge(x,y),z);
}
void print(int x)
{
if(!x) return ;
push_down(x); print(ls);
printf("%lld ",tre[x].dat);
print(rs);
}
}T;
int n,m;
#undef int
int main()
{
#define int long long
srand(time(0));
n=read(); m=read();
for(int i=1;i<=n;i++)
T.root=T.merge(T.root,T.New(i));
for(int i=1,l,r;i<=m;i++)
{
l=read(); r=read();
T.reverse(l,r);
}
T.print(T.root);
return 0;
}
回滚莫队
#include<bits/stdc++.h>
#define int long long
#define ull unsigned long long
#define f() cout<<"Pass"<<endl
using namespace std;
inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
return x*f;
}
const int N=1e5+10;
int n,m,r,len,maxn,top,pos[N],s[N],ans[N],li[N],ri[N];
struct Node
{
int l,r,id;
bool friend operator < (Node x,Node y)
{
if(pos[x.l]==pos[y.l]) return x.r<y.r;
return x.l<y.l;
}
}q[N];
struct node
{
bool opt; int id,val;
}sta[N<<1];
signed main()
{
n=read(); m=read();
len=sqrt(n);
for(int i=1;i<=n;i++)
s[i]=read(),pos[i]=i/len+1;
for(int i=1;i<=m;i++)
q[i].l=read(),q[i].r=read(),q[i].id=i;
sort(q+1,q+m+1);
for(int i=1;i<=m;i++)
{
if(pos[q[i].l]!=pos[q[i-1].l])
{
maxn=0; r=pos[q[i].l]*len;
for(int j=1;j<=n;j++)
li[j]=ri[j]=0;
}
while(r<q[i].r)
{
r++;
li[s[r]]=li[s[r]-1]+1;
ri[s[r]]=ri[s[r]+1]+1;
int temp=li[s[r]]+ri[s[r]]-1;
maxn=max(maxn,temp);
li[s[r]+ri[s[r]]-1]=temp;
ri[s[r]-li[s[r]]+1]=temp;
}
int rec=maxn;
for(int j=q[i].l;j<=min(q[i].r,pos[q[i].l]*len);j++)
{
li[s[j]]=li[s[j]-1]+1;
ri[s[j]]=ri[s[j]+1]+1;
sta[++top]=(node){0,s[j]-li[s[j]]+1,ri[s[j]-li[s[j]]+1]};
sta[++top]=(node){1,ri[s[j]]+s[j]-1,li[ri[s[j]]+s[j]-1]};
int temp=li[s[j]]+ri[s[j]]-1;
rec=max(rec,temp);
li[s[j]+ri[s[j]]-1]=temp;
ri[s[j]-li[s[j]]+1]=temp;
}
while(top)
{
if(!sta[top].opt) ri[sta[top].id]=sta[top].val;
else li[sta[top].id]=sta[top].val;
top--;
}
for(int j=q[i].l;j<=min(q[i].r,pos[q[i].l]*len);j++)
li[s[j]]=ri[s[j]]=0;
ans[q[i].id]=rec;
}
for(int i=1;i<=m;i++)
printf("%lld\n",ans[i]);
return 0;
}
笛卡尔树
/*
给定一个 1~n的排列 p,构建其笛卡尔树。
即构建一棵二叉树,满足:
每个节点的编号满足二叉搜索树的性质。
节点 i 的权值为 pi,每个节点的权值满足小根堆的性质。
*/
void build()
{
int top=0,pos=0;
for(int i=1;i<=n;i++)
{
pos=top;
while(pos&&p[sta[pos]]>p[i]) pos--;
if(pos) rs[sta[pos]]=i;
if(pos<top) ls[i]=sta[pos+1];
sta[++pos]=i; top=pos;
}
}
虚树
bool comp(int x,int y)
{
return dfn[x]<dfn[y];
}
void build(int x)
{
if(!top)
{
sta[++top]=x;
return ;
}
int lca=LCA_ask(x,sta[top]);
while(top>1&&dep[lca]<dep[sta[top-1]])
{
e2.add(sta[top-1],sta[top]);
e2.add(sta[top],sta[top-1]);
top--;
}
if(dep[lca]<dep[sta[top]])
{
e2.add(lca,sta[top]);
e2.add(sta[top],lca);
top--;
}
if(!top||sta[top]!=lca)
sta[++top]=lca;
sta[++top]=x;
}
int main()
{
while(Q--)
{
for(int i=1;i<=m;i++)
{
scanf("%d",&q[i]);
vis[q[i]]=true;
ans[q[i]]=0;
}
if(!vis[1])
{
flag=true;
q[++m]=1;
}
for(int i=1;i<=m;i++)
s[i]=q[i];
sort(s+1,s+m+1,comp);
for(int i=1;i<=m;i++)
build(s[i]);
if(top)
while(--top)
{
e2.add(sta[top],sta[top+1]);
e2.add(sta[top+1],sta[top]);
}
}
}
P2479捉迷藏
KDTree
#include<bits/stdc++.h>
#define int long long
#define ull unsigned long long
#define f() cout<<"Test: "<<endl
#define ls tre[x].l
#define rs tre[x].r
using namespace std;
inline int read()
{
int x=0,f=1; char ch=getchar();
while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
return x*f;
}
const int N=1e5+10,INF=1e18;
bool comp;
int maxn[N],minn[N];
struct Node
{
int d[2],id;
bool friend operator < (Node x,Node y)
{return x.d[comp]>y.d[comp];}
}s[N],temp;
int dist(Node x,Node y)
{
return abs(x.d[0]-y.d[0])+abs(x.d[1]-y.d[1]);
}
struct K_DTree
{
int root,all;
struct Tree
{
int l,r,mn[2],mx[2];
Node dat;
}tre[N];
void push_up(int x)
{
for(int i=0;i<=1;i++)
{
tre[x].mn[i]=tre[x].mx[i]=tre[x].dat.d[i];
if(ls) tre[x].mn[i]=min(tre[x].mn[i],tre[ls].mn[i]),
tre[x].mx[i]=max(tre[x].mx[i],tre[ls].mx[i]);
if(rs) tre[x].mn[i]=min(tre[x].mn[i],tre[rs].mn[i]),
tre[x].mx[i]=max(tre[x].mx[i],tre[rs].mx[i]);
}
}
void build(int &x,int l,int r,int opt)
{
int mid=(l+r)>>1; comp=opt;
nth_element(s+l,s+mid,s+r+1);
tre[x=++all].dat=s[mid];
if(l<mid) build(ls,l,mid-1,opt^1);
if(r>mid) build(rs,mid+1,r,opt^1);
push_up(x);
}
int KD_max(int x,Node p)
{
if(!x) return -INF;
int sum=0;
for(int i=0;i<=1;i++)
sum+=max(abs(tre[x].mn[i]-p.d[i]),abs(tre[x].mx[i]-p.d[i]));
return sum;
}
int KD_min(int x,Node p)
{
if(!x) return INF;
int sum=0;
for(int i=0;i<=1;i++)
sum+=max(0ll,tre[x].mn[i]-p.d[i])+max(0ll,p.d[i]-tre[x].mx[i]);
return sum;
}
void query_max(int x,Node p)
{
if(!x) return ;
int rec=dist(tre[x].dat,p);
if(rec>maxn[p.id]) maxn[p.id]=rec,temp=tre[x].dat;
int mxl=KD_max(ls,p),mxr=KD_max(rs,p);
if(mxl>mxr)
{
if(mxl>maxn[p.id]) query_max(ls,p);
if(mxr>maxn[p.id]) query_max(rs,p);
}
else
{
if(mxr>maxn[p.id]) query_max(rs,p);
if(mxl>maxn[p.id]) query_max(ls,p);
}
}
void query_min(int x,Node p)
{
if(!x) return ;
int rec=dist(tre[x].dat,p);
if(rec<minn[p.id]&&tre[x].dat.id!=p.id)
minn[p.id]=rec,temp=tre[x].dat;
int mnl=KD_min(ls,p),mnr=KD_min(rs,p);
if(mnl<mnr)
{
if(mnl<minn[p.id]) query_min(ls,p);
if(mnr<minn[p.id]) query_min(rs,p);
}
else
{
if(mnr<minn[p.id]) query_min(rs,p);
if(mnl<minn[p.id]) query_min(ls,p);
}
}
}T;
int n,ans=INF;
#undef int
int main()
{
#define int long long
//实际上就是每一层选择不同维度的排序方式,记录每一个区间内可能存在的最优解
n=read();
for(int i=1;i<=n;i++)
s[i].d[0]=read(),s[i].d[1]=read(),s[i].id=i;
T.build(T.root,1,n,0);
memset(minn,0x7f,sizeof(minn));
for(int i=1;i<=n;i++)
{
T.query_max(T.root,s[i]);
maxn[temp.id]=maxn[s[i].id];
T.query_min(T.root,s[i]);
minn[temp.id]=minn[s[i].id];
ans=min(ans,maxn[s[i].id]-minn[s[i].id]);
}
printf("%lld",ans);
return 0;
}