1.线段树
//Twenty
#include<cstdio>
#include<cstdlib>
#include<cstring>
#define lc x<<1
#define rc x<<1|1
#define mid ((l+r)>>1)
using namespace std;
const int maxn=2e6+10;
typedef long long ll;
ll a[maxn],segt[maxn<<2],lazy[maxn<<2];
int n,q,qu,xx,yy,zz;
void build(int x,int l,int r){
if(l==r){segt[x]=a[l];return ;}
build(lc,l,mid);build(rc,mid+1,r);
segt[x]=segt[lc]+segt[rc];
}
void putdown(int x,int l_len,int r_len){
segt[lc]+=lazy[x]*l_len;lazy[lc]+=lazy[x];
segt[rc]+=lazy[x]*r_len;lazy[rc]+=lazy[x];
lazy[x]=0;
}
void updata(int x,int l,int r,int ql,int qr,int v){
if(ql<=l&&r<=qr){segt[x]+=(r-l+1)*v;lazy[x]+=v;return;}
if(lazy[x]) putdown(x,mid-l+1,r-mid);
if(ql<=mid) updata(lc,l,mid,ql,qr,v);
if(qr>mid) updata(rc,mid+1,r,ql,qr,v);
segt[x]=segt[lc]+segt[rc];
}
ll query(int x,int l,int r,int ql,int qr){
if(ql<=l&&r<=qr) return segt[x];
if(lazy[x]) putdown(x,mid-l+1,r-mid);
if(qr<=mid) return query(lc,l,mid,ql,qr);
else if(ql>mid) return query(rc,mid+1,r,ql,qr);
return query(lc,l,mid,ql,qr)+query(rc,mid+1,r,ql,qr);
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)scanf("%d",&a[i]);
build(1,1,n);
scanf("%d",&q);
while(q--){
scanf("%d%d%d",&qu,&xx,&yy);
if(qu==1){
scanf("%d",&zz);
updata(1,1,n,xx,yy,zz);
}
else printf("%lld
",query(1,1,n,xx,yy));
}
return 0;
}
//Twenty
#include<cstdio>
#include<cstdlib>
#include<cstring>
#define lc x<<1
#define rc x<<1|1
#define mid ((l+r)>>1)
using namespace std;
const int maxn=1e6+10;
typedef long long ll;
ll a[maxn],segt[maxn<<2][7],lazy[maxn<<2],temp[7];
int n,q,xx,yy,zz;
char qu[10];
using namespace std;
void build(int x,int l,int r){
if(l==r) {segt[x][a[l]%7]=1; return ;}
build(lc,l,mid);build(rc,mid+1,r);
for(int i=0;i<=6;i++){segt[x][i]=segt[lc][i]+segt[rc][i];}
}
void putdown(int x){
lazy[lc]+=lazy[x];
for(int i=0;i<=6;i++) temp[(i+lazy[x])%7]=segt[lc][i];
for(int i=0;i<=6;i++) segt[lc][i]=temp[i];
lazy[rc]+=lazy[x];
for(int i=0;i<=6;i++) temp[(i+lazy[x])%7]=segt[rc][i];
for(int i=0;i<=6;i++) segt[rc][i]=temp[i];
lazy[x]=0;
}
void updata(int x,int l,int r,int ql,int qr,int v){
if(ql<=l&&r<=qr) {
for(int i=0;i<=6;i++) temp[(i+v)%7]=segt[x][i];
for(int i=0;i<=6;i++) segt[x][i]=temp[i];
lazy[x]+=v; return ; }
if(lazy[x]) putdown(x);
if(ql<=mid) updata(lc,l,mid,ql,qr,v);
if(qr>mid) updata(rc,mid+1,r,ql,qr,v);
for(int i=0;i<=6;i++) segt[x][i]=segt[lc][i]+segt[rc][i];
}
ll query(int x,int l,int r,int ql,int qr){
if(ql<=l&&r<=qr) return segt[x][0];
if(lazy[x]) putdown(x);
if(qr<=mid) return query(lc,l,mid,ql,qr);
else if(ql>mid) return query(rc,mid+1,r,ql,qr);
return query(lc,l,mid,ql,qr)+query(rc,mid+1,r,ql,qr);
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
build(1,1,n);
scanf("%d",&q);
while(q--){
scanf("%s%d%d",&qu,&xx,&yy);
if(qu[0]=='a'){
scanf("%d",&zz);
updata(1,1,n,xx,yy,zz);
}
else printf("%lld
",query(1,1,n,xx,yy));
}
return 0;
}
//Twenty
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<queue>
#include<vector>
#define lc x<<1
#define rc x<<1|1
#define mid ((l+r)>>1)
const int maxn=200050;
typedef long long ll;
char s[10];
ll tmp,nn,qs,a,b,c,n,m;
ll aa[maxn],sgt[maxn<<2],sgd[maxn<<2],sgx[maxn<<2],lzj[maxn<<2],lzc[maxn<<2];
using namespace std;
inline ll read(){
ll ret=0,f=1; char ch=getchar();
while(ch!='-'&&(ch>'9'||ch<'0')) ch=getchar();
if(ch=='-') {f=-1;ch=getchar();}
for(;ch>='0'&&ch<='9';ch=getchar()) ret=ret*10+ch-'0';
return ret*f;
}
void down(int x,int len,int l_len,int r_len){
if(lzc[x]) {
if(lzj[x]) tmp=(sgt[x]-lzj[x]*len)/len;
else tmp=sgt[x]/len;
sgt[lc]=tmp*l_len; lzc[lc]=1; lzj[lc]=0;
sgd[lc]=sgx[lc]=tmp;
sgt[rc]=tmp*r_len; lzc[rc]=1; lzj[rc]=0;
sgd[rc]=sgx[rc]=tmp;
lzc[x]=0;
}
if(lzj[x]){
sgt[lc]+=lzj[x]*l_len; lzj[lc]+=lzj[x];
sgt[rc]+=lzj[x]*r_len; lzj[rc]+=lzj[x];
sgd[lc]+=lzj[x]; sgx[lc]+=lzj[x]; sgd[rc]+=lzj[x]; sgx[rc]+=lzj[x];
lzj[x]=0;
}
}
void build(int x,int l,int r){
if(l==r) {sgd[x]=sgx[x]=sgt[x]=aa[l];return;}
build(lc,l,mid); build(rc,mid+1,r);
sgt[x]=sgt[lc]+sgt[rc];
sgd[x]=max(sgd[lc],sgd[rc]);
sgx[x]=min(sgx[lc],sgx[rc]);
}
void add(int x,int ql,int qr,int l,int r,int v,int cj){
if(l>=ql&&r<=qr) {
if(cj==1) {sgt[x]+=v*(r-l+1); lzj[x]+=v;
sgd[x]+=v; sgx[x]+=v;
}
else {sgt[x]=v*(r-l+1); lzc[x]=1; lzj[x]=0;
sgd[x]=sgx[x]=v;
}
return;
}
if(lzj[x]||lzc[x]) down(x,r-l+1,mid-l+1,r-mid);
if(ql<=mid) add(lc,ql,qr,l,mid,v,cj);
if(qr>mid) add(rc,ql,qr,mid+1,r,v,cj);
sgt[x]=sgt[lc]+sgt[rc];
sgd[x]=max(sgd[lc],sgd[rc]);
sgx[x]=min(sgx[lc],sgx[rc]);
}
ll query(int x,int ql,int qr,int l,int r,int cs){
if(l>=ql&&r<=qr)
{if(cs==1) return sgd[x];
if(cs==2) return sgx[x];
if(cs==3) return sgt[x];
}
if(lzj[x]||lzc[x]) down(x,r-l+1,mid-l+1,r-mid);
if(qr<=mid) return query(lc,ql,qr,l,mid,cs);
else if(ql>mid) return query(rc,ql,qr,mid+1,r,cs);
else {if(cs==3)return query(lc,ql,qr,l,mid,cs)+query(rc,ql,qr,mid+1,r,cs);
if(cs==1) return max(query(lc,ql,qr,l,mid,cs),query(rc,ql,qr,mid+1,r,cs));
if(cs==2) return min(query(lc,ql,qr,l,mid,cs),query(rc,ql,qr,mid+1,r,cs));
}
}
int main()
{
n=read(); m=read();
for(int i=1;i<=n;i++) aa[i]=read();
build(1,1,n);
for(int i=1;i<=m;i++){
scanf("%s",&s); a=read();b=read();
if(s[0]=='a') add(1,a,b,1,n,read(),1);
else if(s[1]=='e') add(1,a,b,1,n,read(),2);
else if(s[1]=='a') printf("%lld
",query(1,a,b,1,n,1));
else if(s[1]=='i') printf("%lld
",query(1,a,b,1,n,2));
else printf("%lld
",query(1,a,b,1,n,3));
}
return 0;
}
2.树状数组
//Twenty
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<queue>
#include<vector>
using namespace std;
const int maxn=500000+5;
int n,m,x,y,k,c[maxn];
int lowbit(int x){
return x&(-x);
}
void add(int x,int v){
for(int i=x;i<=n;i=i+lowbit(i)) c[i]+=v;
}
int sum(int x){
int ans=0;
for(int i=x;i>=1;i=i-lowbit(i)) ans+=c[i];
return ans;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
scanf("%d",&x);
add(i,x);
}
while(m--){
scanf("%d%d%d",&k,&x,&y);
if(k==1) add(x,y);
else printf("%d
",sum(y)-sum(x-1));
}
return 0;
}
//Twenty
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<queue>
#include<vector>
const int maxn=500000+5;
using namespace std;
int n,m,x,y,k,v,tmp,c[maxn];
int lowbit(int x){
return x&(x^(x-1));
}
void add(int x,int v){
for(int i=x;i<=n;i+=lowbit(i)) c[i]+=v;
}
int sum(int x){
int ans=0;
for(int i=x;i>0;i-=lowbit(i)) ans+=c[i];
return ans;
}
int main()
{
ios::sync_with_stdio(false);
cin>>n>>m;
for(int i=1;i<=n;i++){
cin>>x;
add(i,x-tmp);
tmp=x;
}
while(m--){
cin>>k>>x;
if(k==1){
cin>>y>>v;
add(x,v);
add(y+1,-v);
}
else{
cout<<sum(x)<<endl;
}
}
return 0;
}
//Achen
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<queue>
#include<cmath>
const int N=100007;
typedef long long LL;
using namespace std;
int T,ls[N],sum[N],q[N][2];
template<typename T> void read(T &x) {
char ch=getchar(); x=0; T f=1;
while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
if(ch=='-') f=-1,ch=getchar();
for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f;
}
int hash(int x) {return lower_bound(ls+1,ls+ls[0]+1,x)-ls;}
void add(int x,int v) {
for(int i=x;i<=ls[0];i+=(i&(-i)))
sum[i]+=v;
}
int qry(int x) {
int res=0;
for(int i=x;i;i-=(i&(-i)))
res+=sum[i];
return res;
}
void kth(int k) {
int res=0;
for(int i=20;i>=0;i--) {
res+=(1<<i);
if(res>=ls[0]||sum[res]>=k) res-=(1<<i);
else k-=sum[res];
}
printf("%d
",ls[res+1]);
}
#define DEBUG
int main() {
#ifdef DEBUG
freopen(".in","r",stdin);
freopen(".out","w",stdout);
#endif
read(T);
for(int i=1;i<=T;i++) {
read(q[i][0]); read(q[i][1]);
if(q[i][0]!=4) ls[++ls[0]]=q[i][1];
}
sort(ls+1,ls+ls[0]+1);
int tpsz=unique(ls+1,ls+ls[0]+1)-(ls+1); ls[0]=tpsz;
for(int i=1;i<=T;i++) {
switch(q[i][0]) {
case 1:add(hash(q[i][1]),1);break;
case 2:add(hash(q[i][1]),-1);break;
case 3:printf("%d
",qry(hash(q[i][1])-1)+1);break;
case 4:kth(q[i][1]);break;
case 5:kth(qry(hash(q[i][1])-1));break;
case 6:kth(qry(hash(q[i][1]))+1);break;
}
}
return 0;
}
3.ZKW线段树
//Twenty
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<queue>
#include<vector>
const int maxn=200005;
int m=1,x,y,T,n,a[maxn<<2];
char q[10];
using namespace std;
void build(){
for(;m<=n+1;m<<=1);
for(int i=m+1;i<=m+n;i++) scanf("%d",&a[i]);
for(int i=m-1;i>0;i--) a[i]=a[i<<1]+a[i<<1|1];
}
void add(int x,int v){
int k=x+m; a[k]+=v;
for(k>>=1;k;k>>=1) a[k]=a[k<<1]+a[k<<1|1];
}
int query(int l,int r){
int ret=0;
for(int i=m+l-1,j=m+r+1;i^j^1;i>>=1,j>>=1){
if(~i&1) ret+=a[i^1];
if(j&1) ret+=a[j^1];
}
return ret;
}
int main()
{
scanf("%d",&T);
for(int t=1;t<=T;t++){
scanf("%d",&n);
cout<<"Case "<<t<<":"<<endl;
build();
for(;;){
scanf("%s",&q);
if(q[0]=='E') break;
scanf("%d%d",&x,&y);
if(q[0]=='A') add(x,y);
else if(q[0]=='S') add(x,-y);
else printf("%d
",query(x,y));
}
m=1;memset(a,0,sizeof(a));
}
return 0;
}
//Twenty
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<queue>
#include<vector>
const int maxn=200005;
int f,m=1,x,y,T,n,a[maxn<<2];
char q[5];
using namespace std;
void build(){
for(;m<=n+1;m<<=1);
for(int i=m+1;i<=m+n;i++) scanf("%d",&a[i]);
for(int i=m-1;i>0;i--) a[i]=max(a[i<<1],a[i<<1|1]);
}
void add(int x,int v){
int k=x+m; a[k]=v;
for(k>>=1;k;k>>=1) a[k]=max(a[k<<1],a[k<<1|1]);
}
int query(int l,int r){
int ret=0;
for(int i=m+l-1,j=m+r+1;i^j^1;i>>=1,j>>=1){
if(~i&1) ret=max(ret,a[i^1]);
if(j&1) ret=max(ret,a[j^1]);
}
return ret;
}
int main()
{
while(scanf("%d%d",&n,&f)!=EOF){
build();
while(f--){
scanf("%s%d%d",&q,&x,&y);
if(q[0]=='U') add(x,y);
else printf("%d
",query(x,y));
}
m=1;memset(a,0,sizeof(a));
}
return 0;
}
4.ST表
//Twenty
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<queue>
#include<vector>
const int maxn=1e6+299;
using namespace std;
int n,m,l,r,st[maxn][20];
void make_st(){
for(int j=1;j<=20;j++)
for(int i=1;i+(1<<j)-1<=n;i++)
st[i][j]=max(st[i][j-1],st[i+(1<<(j-1))][j-1]);
}
int query(int l,int r){
int k=0;
while(l+(1<<k)-1<=r) k++;
if(k) k--;
return max(st[l][k],st[r-(1<<k)+1][k]);
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) scanf("%d",&st[i][0]);
make_st();
while(m--){
scanf("%d%d",&l,&r);
printf("%d
",query(l,r));
}
return 0;
}
5.可持久化线段树
//Twenty
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<queue>
#include<vector>
const int maxn=100005;
int sz,T,n,m,rt[maxn],tot,lc[maxn*20],rc[maxn*20],sum[maxn*20],a[maxn],b[maxn];
using namespace std;
void update(int &o,int l,int r,int last,int v){
o=++tot;
lc[o]=lc[last];
rc[o]=rc[last];
sum[o]=sum[last]+1;
if(l==r) return;
int mid=(l+r)>>1;
if(v<=mid) update(lc[o],l,mid,lc[last],v);
else update(rc[o],mid+1,r,rc[last],v);
}
int query(int ql,int qr,int l,int r,int k){
if(l==r) return l;
int mid=(l+r)>>1;
int cnt=sum[lc[qr]]-sum[lc[ql]];
if(cnt>=k) return query(lc[ql],lc[qr],l,mid,k);
else return query(rc[ql],rc[qr],mid+1,r,k-cnt);
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) { scanf("%d",&a[i]);b[i]=a[i];}
sort(b+1,b+n+1);
sz=unique(b+1,b+n+1)-(b+1);
tot=0;
rt[0]=++tot;
//build(rt[0],1,sz);
for(int i=1;i<=n;i++) a[i]=lower_bound(b+1,b+sz+1,a[i])-b;
for(int i=1;i<=n;i++) update(rt[i],1,sz,rt[i-1],a[i]);
for(int i=1;i<=m;i++){
int l,r,k;scanf("%d%d%d",&l,&r,&k);
printf("%d
",b[query(rt[l-1],rt[r],1,sz,k)]);
}
return 0;
}
6.树链剖分
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<queue>
#include<vector>
#define rc x<<1|1
#define lc x<<1
#define mid ((l+r)>>1)
using namespace std;
const int maxn=150005;
int x,y,z,k,n,q,s,mod,w[maxn],fir[maxn],next[maxn*2],to[maxn*2],father[maxn],R[maxn],size[maxn],tid[maxn];
int top[maxn],e[maxn],in[maxn],segt[maxn<<2],lazy[maxn<<2];
int ecnt,tot;
inline void add(int u,int v){
next[++ecnt]=fir[u];fir[u]=ecnt;to[ecnt]=v;in[u]++;
next[++ecnt]=fir[v];fir[v]=ecnt;to[ecnt]=u;in[v]++;
}
void down(int x,int l_len,int r_len){
if(l_len) lazy[lc]+=lazy[x]%mod, segt[lc]+=l_len*lazy[x]%mod;
if(r_len) lazy[rc]+=lazy[x]%mod, segt[rc]+=r_len*lazy[x]%mod;
lazy[x]=0;
}
void change(int x,int l,int r,int ql,int qr,int v){
if(l>=ql&&r<=qr) {segt[x]+=v*(r-l+1);lazy[x]+=v;lazy[x]%=mod;return;}
if(lazy[x]) down(x,mid-l+1,r-mid);
if(ql<=mid) change(lc,l,mid,ql,qr,v);
if(qr>mid) change(rc,mid+1,r,ql,qr,v);
segt[x]=(segt[lc]+segt[rc])%mod;
}
int query(int x,int l,int r,int ql,int qr){
if(l>=ql&&r<=qr) return segt[x];
if(lazy[x]) down(x,mid-l+1,r-mid);
if(qr<=mid) return query(lc,l,mid,ql,qr)%mod;
if(ql>mid) return query(rc,mid+1,r,ql,qr)%mod;
return (query(lc,l,mid,ql,qr)+query(rc,mid+1,r,ql,qr))%mod;
}
void dfs(int x,int fa){
father[x]=fa;R[x]=R[fa]+1;size[x]=1;
for(int i=fir[x];i;i=next[i]){
if(to[i]!=fa){
dfs(to[i],x);
size[x]+=size[to[i]];
}
}
}
void dfs2(int x){
tid[x]=++tot;
change(1,1,n,tot,tot,w[x]);
int mson=0;
if(in[x]==1&&x!=s){
e[x]=x;
return;
}
for(int i=fir[x];i;i=next[i])
if(size[to[i]]<size[x]&&size[to[i]]>size[mson]) mson=to[i];
top[mson]=top[x];
dfs2(mson); e[x]=e[mson];
for(int i=fir[x];i;i=next[i]){
if(size[to[i]]<size[x]&&to[i]!=mson){
top[to[i]]=to[i];
dfs2(to[i]);
e[x]=e[to[i]];
}
}
}
void schange(int x,int y,int z){
while(top[x]!=top[y]){
if(R[top[x]]<R[top[y]]) swap(x,y);
change(1,1,n,tid[top[x]],tid[x],z);
x=father[top[x]];
}
if(tid[x]>tid[y]) swap(x,y);
change(1,1,n,tid[x],tid[y],z);
}
int squery(int x,int y){
int ret=0;
while(top[x]!=top[y]){
if(R[top[x]]<R[top[y]]) swap(x,y);
ret+=query(1,1,n,tid[top[x]],tid[x]); ret=ret%mod;
x=father[top[x]];
}
if(tid[x]>tid[y]) swap(x,y);
ret+=query(1,1,n,tid[x],tid[y]); ret=ret%mod;
return ret;
}
int main()
{
scanf("%d%d%d%d",&n,&q,&s,&mod);
for(int i=1;i<=n;i++) scanf("%d",&w[i]);
for(int i=1;i<n;i++){
scanf("%d%d",&x,&y);
add(x,y);
}
father[s]=s;top[s]=s;
dfs(s,s);dfs2(s);
for(int i=1;i<=q;i++){
scanf("%d",&k);
if(k==1){
scanf("%d%d%d",&x,&y,&z);
schange(x,y,z);
}
else if(k==2){
scanf("%d%d",&x,&y);
printf("%d
",squery(x,y));
}
else if(k==3){
scanf("%d%d",&x,&z);
change(1,1,n,tid[x],tid[e[x]],z);
}
else{
scanf("%d",&x);
printf("%d
",query(1,1,n,tid[x],tid[e[x]]));
}
}
return 0;
}
7.treap
//Achen #include<algorithm> #include<iostream> #include<cstring> #include<cstdlib> #include<vector> #include<cstdio> #include<queue> #include<cmath> #include<set> #define For(i,a,b) for(int i=(a);i<=(b);i++) #define Rep(i,a,b) for(int i=(a);i>=(b);i--) const int N=200007; typedef long long LL; typedef double db; using namespace std; int T,o,x; template<typename T> void read(T &x) { char ch=getchar(); x=0; T f=1; while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar(); if(ch=='-') f=-1,ch=getchar(); for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f; } int rt,tot,l[N],r[N],v[N],hr[N],sz[N]; #define lc l[x] #define rc r[x] void update(int x) { sz[x]=sz[lc]+sz[rc]+1; } void left(int &x) { int y=r[x]; r[x]=l[y]; l[y]=x; update(x); x=y; update(y); } void right(int &x) { int y=l[x]; l[x]=r[y]; r[y]=x; update(x); x=y; update(y); } void insert(int &x,int y) { if(!x) { x=++tot; v[x]=y; hr[x]=rand(); sz[x]=1; l[x]=r[x]=0; return; } if(y<=v[x]) { insert(lc,y); if(hr[lc]>hr[x]) right(x); } else { insert(rc,y); if(hr[rc]>hr[x]) left(x); } update(x); } void del(int &x,int y) { if(!x) return; if(v[x]==y) { if(!lc) x=rc; else if(!rc) x=lc; else { if(hr[lc]>hr[rc]) { right(x); del(rc,y); } else { left(x); del(lc,y); } update(x); } } else { if(y<v[x]) del(lc,y); else del(rc,y); update(x); } } int rak(int rt,int y) { int rs=1; for(int x=rt;x;) { if(v[x]<y) rs+=sz[lc]+1,x=rc; else x=lc; } return rs; } int kth(int rt,int k) { for(int x=rt;x;) { if(sz[lc]+1==k) return v[x]; if(sz[lc]+1<k) k-=(sz[lc]+1),x=rc; else x=lc; } return -1; } int pre(int rt,int y) { int rs=-1; for(int x=rt;x;) { if(v[x]<y) rs=v[x],x=rc; else x=lc; } return rs; } int nxt(int rt,int y) { int rs=-1; for(int x=rt;x;) { if(v[x]>y) rs=v[x],x=lc; else x=rc; } return rs; } int main() { #ifdef DEBUG freopen(".in","r",stdin); freopen(".out","w",stdout); #endif srand(998244353); read(T); while(T--) { read(o); read(x); switch(o) { case 1:insert(rt,x);break; case 2:del(rt,x);break; case 3:printf("%d ",rak(rt,x));break; case 4:printf("%d ",kth(rt,x));break; case 5:printf("%d ",pre(rt,x));break; case 6:printf("%d ",nxt(rt,x));break; } } return 0; }
//Achen
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<vector>
#include<queue>
#include<ctime>
#include<cmath>
const int N=100007;
typedef long long LL;
using namespace std;
int T,rt;
template<typename T> void read(T &x) {
char ch=getchar(); x=0; T f=1;
while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
if(ch=='-') f=-1,ch=getchar();
for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f;
}
int n,v[N],hr[N],l[N],r[N],sz[N],tot;
#define lc l[x]
#define rc r[x]
void update(int x) {sz[x]=sz[lc]+sz[rc]+1;}
int merge(int x,int y) {
if(!(x*y)) return x^y;
if(hr[x]<hr[y]) rc=merge(rc,y);
else {
swap(x,y);
lc=merge(y,lc);
}
update(x);
return x;
}
#define pr pair<int,int>
#define se second
#define fi first
pr split(int x,int k) {
if(!x) return make_pair(0,0);
pr p;
if(sz[lc]>=k) {
p=split(lc,k);
lc=p.se; p.se=x;
}
else {
p=split(rc,k-sz[lc]-1);
rc=p.fi; p.fi=x;
}
update(x);
return p;
}
int cre(int y) {
int x=++tot;
hr[x]=rand();
v[x]=y;
sz[x]=1;
return x;
}
int rank(int y) {
int res=1;
for(int x=rt;x;) {
if(v[x]<y) res+=(sz[lc]+1),x=rc;
else x=lc;
}
return res;
}
int kth(int k) {
int res=-1;
for(int x=rt;x;) {
if(sz[lc]+1==k) return v[x];
if(sz[lc]+1>k) x=lc;
else k-=(sz[lc]+1),x=rc;
}
}
int pre(int y) {
int res=-1;
for(int x=rt;x;) {
if(v[x]<y) res=v[x],x=rc;
else x=lc;
}
return res;
}
int nxt(int y) {
int res=-1;
for(int x=rt;x;) {
if(v[x]>y) res=v[x],x=lc;
else x=rc;
}
return res;
}
void insert(int x,int y) {
int z=cre(y);
int k=rank(y);
pr p=split(x,k-1);
rt=merge(p.fi,z);
rt=merge(rt,p.se);
}
void del(int x,int y) {
int k=rank(y);
pr p=split(x,k-1);
pr q=split(p.se,1);
rt=merge(p.fi,q.se);
}
int main() {
srand(time(0));
read(T);
while(T--) {
int o,x;
read(o); read(x);
switch(o) {
case 1:insert(rt,x);break;
case 2:del(rt,x);break;
case 3:printf("%d
",rank(x));break;
case 4:printf("%d
",kth(x));break;
case 5:printf("%d
",pre(x));break;
case 6:printf("%d
",nxt(x));break;
}
}
return 0;
}
//Achen
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<vector>
#include<queue>
#include<ctime>
#include<cmath>
const int N=100007;
typedef long long LL;
using namespace std;
int rt,n,m,tot,ch[N][2],hr[N],sz[N],flip[N];
template<typename T> void read(T &x) {
char ch=getchar(); x=0; T f=1;
while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
if(ch=='-') f=-1,ch=getchar();
for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f;
}
#define lc ch[x][0]
#define rc ch[x][1]
void update(int x) {sz[x]=sz[lc]+sz[rc]+1;}
int build(int l,int r) {
if(l>r) return 0;
int mid=((l+r)>>1);
int tplc=build(l,mid-1);
int x=++tot;
hr[x]=rand();
lc=tplc;
rc=build(mid+1,r);
update(x);
return x;
}
void down(int x) {
if(!flip[x]) return;
swap(lc,rc);
if(lc) flip[lc]^=1;
if(rc) flip[rc]^=1;
flip[x]^=1;
}
#define pr pair<int,int>
#define fi first
#define se second
pr split(int x,int k) {
if(!x) return make_pair(0,0);
pr p;
down(x);
if(sz[lc]>=k) {
p=split(lc,k);
lc=p.se; p.se=x;
}
else {
p=split(rc,k-sz[lc]-1);
rc=p.fi; p.fi=x;
}
update(x);
return p;
}
int merge(int x,int y) {
if(!(x*y)) return x^y;
if(hr[x]<hr[y]) {
down(x);
rc=merge(rc,y);
}
else {
swap(x,y);
down(x);
lc=merge(y,lc);
}
update(x);
return x;
}
void rever(int l,int r) {
pr p=split(rt,l-1);
pr q=split(p.se,r-l+1);
flip[q.fi]^=1;
rt=merge(merge(p.fi,q.fi),q.se);
}
void print(int x) {
down(x);
if(lc) print(lc);
printf("%d ",x);
if(rc) print(rc);
}
int main() {
srand(time(0));
read(n); read(m);
rt=build(1,n);
while(m--) {
int l,r;
read(l); read(r);
rever(l,r);
}
print(rt);
return 0;
}
8.splay
//Twenty
#include <cstdio>
#define Maxn 1000000
using namespace std;
int f[Maxn];
int ch[Maxn][2];
int key[Maxn];
int cnt[Maxn];
int siz[Maxn];
int sz,root;
void clear(int x) {
ch[x][0]=ch[x][1]=f[x]=cnt[x]=key[x]=siz[x]=0;
}
int getson(int x) {return ch[f[x]][1]==x;}
void update(int x) {
siz[x]=cnt[x];
if (ch[x][0]) siz[x]+=siz[ch[x][0]];
if (ch[x][1]) siz[x]+=siz[ch[x][1]];
}
int rotate(int x) {
int fa=f[x],fafa=f[fa],k=getson(x);
ch[fa][k]=ch[x][k^1];f[ch[fa][k]]=fa;
ch[x][k^1]=fa;f[fa]=x;f[x]=fafa;
if (fafa)
ch[fafa][ch[fafa][1]==fa]=x;
update(fa);update(x);
}
void splay(int x) {
for (int fa;fa=f[x];rotate(x))
if (f[fa])
rotate(getson(x)==getson(fa) ? fa : x);
root=x;
}
int pre() {
int now=ch[root][0];
while(ch[now][1])
now=ch[now][1];
return now;
}
int nex() {
int now=ch[root][1];
while(ch[now][0])
now=ch[now][0];
return now;
}
int findpos(int v) {
int now=root,ans=0;
while(1) {
if (v<key[now])
now=ch[now][0];
else {
ans+=ch[now][0]?siz[ch[now][0]]:0;
if (v==key[now]) {
splay(now);
return ans+1;
}
ans+=cnt[now];
now=ch[now][1];
}
}
}
int findx(int x) {
int now=root;
while(1) {
if (ch[now][0] && x<=siz[ch[now][0]])
now=ch[now][0];
else {
int temp=(ch[now][0]?siz[ch[now][0]]:0)+cnt[now];
if (x<=temp)
return key[now];
x-=temp;
now=ch[now][1];
}
}
}
void create(int v) {
sz++;
ch[sz][0]=ch[sz][1]=f[sz]=0;
key[sz]=v;
cnt[sz]=1;
siz[sz]=1;
}
void insert(int v) {
if (!root)
create(v),root=sz;
else {
int now=root,fa=0;
while(1) {
if (key[now]==v) {
cnt[now]++;
splay(now);
break;
}
fa=now;
now=ch[fa][v>key[fa]];
if (!now) {
create(v);
f[sz]=fa;
ch[fa][v>key[fa]]=sz;
update(fa);
splay(sz);
break;
}
}
}
}
void del(int x) {
int t=findpos(x);
if (cnt[root]>1) {
cnt[root]--;
update(root);
return;
}
if (!ch[root][0] && !ch[root][1]) {
clear(root);
root=0;
return;
}
if (!ch[root][1]) {
int temp=root;
root=ch[root][0];
f[root]=0;
clear(temp);
return;
}
else
if (!ch[root][0]) {
int temp=root;
root=ch[root][1];
f[root]=0;
clear(temp);
return;
}
int pre1=pre(),temp=root;
splay(pre1);
f[ch[temp][1]]=root;
ch[root][1]=ch[temp][1];
clear(temp);
update(root);
}
int main()
{
int n,opt,x;
scanf("%d",&n);
for (int i=1;i<=n;++i) {
scanf("%d%d",&opt,&x);
switch(opt) {
case 1: insert(x); break;
case 2: del(x); break;
case 3: printf("%d
",findpos(x)); break;
case 4: printf("%d
",findx(x)); break;
case 5: insert(x); printf("%d
",key[pre()]); del(x); break;
case 6: insert(x); printf("%d
",key[nex()]); del(x); break;
}
}
}
//Twenty
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<queue>
#include<vector>
#define lc ch[x][0]
#define rc ch[x][1]
using namespace std;
const int maxn=100005;
int n,T,l,r,root,cnt,flip[maxn],ch[maxn][2],p[maxn],sz[maxn];
void update(int x) {sz[x]=sz[lc]+sz[rc]+1;}
void down(int x){
if(!flip[x]) return;
swap(lc,rc);
flip[lc]^=1;flip[rc]^=1;
flip[x]=0;
}
int kth(int x,int a){
for(;x;){
down(x);
int k=sz[lc]+1;
if(k==a) return x;
if(k<a) a-=k,x=rc;
else x=lc;
}
}
void rotate(int x){
int y=p[x],z=p[y];
if(z) ch[z][y==ch[z][1]]=x; p[x]=z;
l=(x==ch[y][1]),r=l^1;
ch[y][l]=ch[x][r]; p[ch[y][l]]=y;
ch[x][r]=y; p[y]=x;
update(y);
update(x);
}
void splay(int x,int FA){
if(p[x]!=FA){
static int s[maxn],top=0;
for(int i=x;i;i=p[i]) s[++top]=i;
while(top) down(s[top--]);
}
for(;p[x]!=FA;rotate(x)){
int y=p[x],z=p[y];
if(z!=FA){
((ch[z][1]==y)^(ch[y][1]==x))?rotate(x):rotate(y);
}
}
if(!FA) root=x;
}
void rever(int l,int r){
l=kth(root,l);r=kth(root,r+2);
splay(l,0);
splay(r,l);
int x=ch[root][1];
flip[lc]^=1;
int now=ch[r][0];
ch[r][0]=0;
update(r);
update(root);
x=kth(root,n-sz[now]+1);
splay(x,0);
x=rc; lc=now; update(x); update(root);
}
int build(int n){
if(!n) return 0;
l=build(n>>1);
int x=++cnt;
lc=l;
r=build(n-(n>>1)-1);
rc=r;
if(lc) p[lc]=x;
if(rc) p[rc]=x;
update(x);
return x;
}
void print(int x){
if(!x) return;
down(x);
print(lc);
if(x>=2&&x<=n+1) printf("%d ",x-1);
print(rc);
}
int main()
{
scanf("%d%d",&n,&T);
root=build(n+2);
while(T--){
scanf("%d%d",&l,&r);
rever(l,r);
}
print(root);
return 0;
}
//Twenty
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<queue>
#include<vector>
#define lc ch[x][0]
#define rc ch[x][1]
using namespace std;
const int maxn=100005;
int aa,bb,tot,root,n,m,ch[maxn][2],p[maxn],flip[maxn],sz[maxn];
void update(int x) {sz[x]=sz[lc]+sz[rc]+1;}
void down(int x){
if(!flip[x]) return;
swap(lc,rc);
flip[x]^=1;
flip[lc]^=1;
flip[rc]^=1;
}
void rotate(int x){
int y=p[x],z=p[y],l=(x==ch[y][1]),r=l^1;
if(z) ch[z][y==ch[z][1]]=x; p[x]=z;
ch[y][l]=ch[x][r]; p[ch[y][l]]=y;
ch[x][r]=y; p[y]=x;
update(y); update(x);
}
void splay(int x,int FA){
if(p[x]==FA) return;
static int s[maxn],top;
for(int i=x;i;i=p[i]) s[++top]=i;
while(top) down(s[top--]);
for(;p[x]!=FA;rotate(x)){
int y=p[x],z=p[y];
if(z!=FA){
((x==ch[y][1])^(y==ch[z][1]))?rotate(x):rotate(y);
}
}
if(FA==0) root=x;
}
int build(int n){
if(!n) return 0;
int ll=build(n>>1);
int x=++tot;
lc=ll;
rc=build(n-(n>>1)-1);
if(lc) p[lc]=x;
if(rc) p[rc]=x;
update(x);
return x;
}
int kth(int k){
for(int x=root;x;){
down(x);
if(sz[lc]+1==k) return x;
if(sz[lc]+1<k) k-=(sz[lc]+1),x=rc;
else x=lc;
}
}
void print(int x){
if(!x) return;
down(x);
print(lc);
if(x>1&&x<n+2) printf("%d
",x-1);
print(rc);
}
void rever(int l,int r){
int ll=kth(l),rr=kth(r+2);
//print(root);
splay(ll,0); splay(rr,ll);
flip[ch[rr][0]]^=1;
int now=ch[rr][0];
ch[rr][0]=0;
update(rr);
update(root);
int x=kth(n-sz[now]+1);
splay(x,0);
x=rc; lc=now; p[now]=x; update(x); update(root);
}
int main()
{
scanf("%d%d",&n,&m);
root=build(n+2);
while(m--){
scanf("%d%d",&aa,&bb);
rever(aa,bb);
}
print(root);
return 0;
}
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<queue>
#include<vector>
#include<ctime>
#define lc ch[x][0]
#define rc ch[x][1]
typedef long long LL;
const int maxn=100000+299;
using namespace std;
int tt,root,tot,T,op,x,sz[maxn],ch[maxn][2],v[maxn],cnt[maxn],p[maxn];
inline int read() {
char ch=getchar(); int f=1,ret=0;
while(ch!='-'&&(ch>'9'||ch<'0')) ch=getchar();
if(ch=='-') f=-1,ch=getchar();
for(;ch>='0'&&ch<='9';ch=getchar()) ret=ret*10+ch-'0';
return ret*f;
}
void update(int x) {sz[x]=sz[lc]+sz[rc]+cnt[x];}
void rotate(int x) {
int y=p[x],z=p[y],l=(x==ch[y][1]),r=l^1;
if(z) ch[z][y==ch[z][1]]=x; p[x]=z;
ch[y][l]=ch[x][r]; p[ch[x][r]]=y;
ch[x][r]=y; p[y]=x;
update(y); update(x);
}
void splay(int x) {
if(x==root) return;
for(;p[x];rotate(x)) {
int y=p[x],z=p[y];
if(z) (y==ch[z][1])^(x==ch[y][1])?rotate(x):rotate(y);
}
root=x;
}
void build(int &x,int y) {
x=++tot;
sz[x]=cnt[x]=1;
v[x]=y;
lc=rc=0;
}
int insert(int x,int y) {
int res=0;
if(!root) {build(root,y); return root;}
if(v[x]==y) {cnt[x]++; res=x;}
if(v[x]<y) {
if(rc) res=insert(rc,y);
else {build(rc,y); p[rc]=x; res=rc;}
}
if(v[x]>y) {
if(lc) res=insert(lc,y);
else {build(lc,y); p[lc]=x; res=lc;}
}
update(x);
return res;
}
int rank(int y) {
int res=1;
for(int x=root;x;) {
if(v[x]==y) {
splay(x); return sz[lc]+1;
}
if(v[x]>y) x=lc;
else x=rc;
}
}
int kth(int k) {
int res=0;
for(int x=root;x;) {
if(sz[lc]+1<=k&&sz[lc]+cnt[x]>=k) return v[x];
if(sz[lc]+1>k) x=lc;
else k-=(sz[lc]+cnt[x]),x=rc;
}
}
int pre(int y) {
int x=root; x=lc;
while(rc) {
x=rc;
}
return x;
}
int nxt(int y) {
int x=root; x=rc;
while(lc) {
x=lc;
}
return x;
}
void del(int x,int y) {
if(!x) return;
for(;;) {
if(!x) return;
int fa=0;
if(v[x]==y) {
splay(x);
if(cnt[x]>1) cnt[x]--;
else if(!lc) {if(rc) p[rc]=fa; root=rc;}
else if(!rc) {if(lc) p[lc]=fa; root=lc;}
else {
int z=pre(x),tp;
splay(z);
tp=ch[ch[root][1]][1];
ch[root][1]=tp;
p[tp]=root;
update(root);
}
update(x);
return;
}
fa=x;
if(v[x]<y) x=rc;
else x=lc;
}
}
int main()
{
T=read();
while(T--) {
op=read(); x=read();
switch(op){
case 1:x=insert(root,x);splay(x);break;
case 2:del(root,x);break;
case 3:printf("%d
",rank(x));break;
case 4:printf("%d
",kth(x));break;
case 5:tt=insert(root,x);splay(tt);printf("%d
",v[pre(x)]);del(root,x);break;
case 6:tt=insert(root,x);splay(tt);printf("%d
",v[nxt(x)]);del(root,x);break;
}
}
return 0;
}
---------------------------------------------------------------------
12.2更新
改进后的比之前短又好看又跑得快的splay
//Achen
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<vector>
#include<queue>
#include<cmath>
#include<ctime>
const int N=100007;
typedef long long LL;
using namespace std;
int T,o,xx;
namespace RD{
const int sz=1<<15|1;
char ch,buf[sz],*l,*r;
void gechar(char &c) {
if(l==r) r=(l=buf)+fread(buf,1,sz,stdin);
c = l==r?EOF:*l++;
}
template<typename T> void read(T &x) {
gechar(ch); x=0; T f=1;
while(ch!='-'&&(ch<'0'||ch>'9')) gechar(ch);
if(ch=='-') f=-1,gechar(ch);
for(;ch>='0'&&ch<='9';gechar(ch)) x=x*10+ch-'0'; x*=f;
}
}
int rt,tot,v[N],ch[N][2],f[N],sz[N];
#define lc ch[x][0]
#define rc ch[x][1]
void update(int x) {sz[x]=sz[lc]+sz[rc]+1;}
void rotate(int x) {
int y=f[x],z=f[y],l=(x==ch[y][1]),r=l^1;
if(z) ch[z][y==ch[z][1]]=x; f[x]=z;
ch[y][l]=ch[x][r]; f[ch[x][r]]=y;
ch[x][r]=y; f[y]=x;
update(y); update(x);
}
void splay(int &rt,int x,int FA) {
if(f[x]==FA) return;
for(;f[x]!=FA;rotate(x)) {
int y=f[x],z=f[y];
if(z!=FA) (x==ch[x][1])^(y==ch[z][1])?rotate(x):rotate(y);
}
if(!FA) rt=x;
}
int cre(int y) {
int x=++tot;
v[x]=y;
sz[x]=1;
return x;
}
void insert(int &rt,int y) {
int fa=0,l=1;
for(int x=rt;;) {
if(!x) {
x=cre(y);
if(fa) ch[fa][l]=x;
else rt=x;
f[x]=fa;
splay(rt,x,0);
return;
}
if(y<=v[x]) fa=x,x=lc,l=0;
else fa=x,x=rc,l=1;
}
}
int rank(int &rt,int y) {
int res=1,tp=0;
for(int x=rt;x;) {
if(v[x]==y) tp=x,x=lc;
else if(v[x]<y) res+=(sz[lc]+1),x=rc;
else x=lc;
}
if(tp) splay(rt,tp,0);
return res;
}
int kth(int &rt,int k) {
for(int x=rt;x;) {
if(sz[lc]+1==k) return x;
if(sz[lc]+1<k) k-=(sz[lc]+1),x=rc;
else x=lc;
}
}
int pre(int rt,int y) {
int res=-1;
for(int x=rt;x;) {
if(v[x]<y) res=v[x],x=rc;
else x=lc;
}
return res;
}
int nxt(int rt,int y) {
int res=-1;
for(int x=rt;x;) {
if(v[x]>y) res=v[x],x=lc;
else x=rc;
}
return res;
}
void del(int &rt,int x) {
int tp=rank(rt,x);
if(tp==1||tp==sz[rt]) {
if(ch[rt][0]) rt=ch[rt][0],f[rt]=0;
else rt=ch[rt][1],f[rt]=0;
}
else {
int y=kth(rt,tp-1);
splay(rt,y,0);
int z=kth(rt,tp+1);
splay(rt,z,y);
f[ch[z][0]]=0; ch[z][0]=0;
update(z); update(y);
}
}
int main() {
#ifdef DEBUG
freopen("1.in","r",stdin);
freopen("1.out","w",stdout);
#endif
RD::read(T);
while(T--) {
RD::read(o); RD::read(xx);
switch(o) {
case 1:insert(rt,xx);break;
case 2:del(rt,xx);break;
case 3:printf("%d
",rank(rt,xx));break;
case 4:printf("%d
",v[kth(rt,xx)]);break;
case 5:printf("%d
",pre(rt,xx));break;
case 6:printf("%d
",nxt(rt,xx));break;
}
}
return 0;
}
12.4 替罪羊树
//Achen
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<vector>
#include<queue>
#include<ctime>
#include<cmath>
const int N=100007*20;
typedef long long LL;
typedef double db;
using namespace std;
int T,o,xx,rt;
namespace RD{
const int sz=1<<15|1;
char ch,buf[sz],*l,*r;
void gechar(char &c) {
if(l==r) r=(l=buf)+fread(buf,1,sz,stdin);
c = l==r?EOF:*l++;
}
template<typename T> void read(T &x) {
gechar(ch); x=0; T f=1;
while(ch!='-'&&(ch<'0'||ch>'9')) gechar(ch);
if(ch=='-') f=-1,gechar(ch);
for(;ch>='0'&&ch<='9';gechar(ch)) x=x*10+ch-'0'; x*=f;
}
}
int tot,ch[N][2],p[N],v[N],sz[N],E[N];
#define lc ch[x][0]
#define rc ch[x][1]
int update(int x) {sz[x]=sz[lc]+sz[rc]+1;}
int bal(int x) {
return 0.75*sz[x]>=(db)sz[lc]&&0.75*sz[x]>=(db)sz[rc];
}
int findx(int y) {
for(int x=rt;x;) {
if(v[x]==y) return x;
if(v[x]<y) x=rc;
else x=lc;
}
}
void tra(int x){
if(lc) tra(lc);
E[++E[0]]=x;
if(rc) tra(rc);
}
int build(int l,int r) {
if(l>r) return 0;
int mid=(l+r)>>1;
int x=E[mid];
lc=build(l,mid-1); p[lc]=x;
rc=build(mid+1,r); p[rc]=x;
update(x);
return x;
}
void rebuild(int x) {
E[0]=0; tra(x);
int y=p[x],z=build(1,E[0]);
if(y) ch[y][x==ch[y][1]]=z; p[z]=y;
if(x==rt) rt=z;
}
int cre(int y) {
int x=++tot;
v[x]=y;
sz[x]=1;
return x;
}
void insert(int y) {
int fa=0,l=1,z=cre(y);
for(int x=rt;;) {
if(!x) {
x=z; p[x]=fa;
if(fa) ch[fa][l]=x;
else rt=x;
break;
}
sz[x]++;
if(v[x]<y) fa=x,l=1,x=rc;
else fa=x,l=0,x=lc;
}
int tp=0;
for(int x=z;x;x=p[x]) if(!bal(x)) tp=x;
if(tp) rebuild(tp);
}
void del(int x) {
if(lc&&rc) {
int y=lc;
while(ch[y][1]) y=ch[y][1];
v[x]=v[y];
x=y;
}
int son=lc?lc:rc;
p[son]=p[x];
if(p[x]) ch[p[x]][x==ch[p[x]][1]]=son;
else rt=son;
for(int i=p[son];i;i=p[i]) sz[i]--;
}
int rank(int y) {
int res=1;
for(int x=rt;x;) {
if(v[x]<y) res+=sz[lc]+1,x=rc;
else x=lc;
}
return res;
}
int kth(int y) {
for(int x=rt;x;) {
if(sz[lc]+1==y) return v[x];
if(sz[lc]+1<y) y-=(sz[lc]+1),x=rc;
else x=lc;
}
}
int pre(int y) {
int res=-1;
for(int x=rt;x;) {
if(v[x]<y) res=v[x],x=rc;
else x=lc;
}
return res;
}
int nxt(int y) {
int res=-1;
for(int x=rt;x;) {
if(v[x]>y) res=v[x],x=lc;
else x=rc;
}
return res;
}
int main() {
RD::read(T);
while(T--) {
RD::read(o); RD::read(xx);
switch(o) {
case 1:insert(xx);break;
case 2:del(findx(xx));break;
case 3:printf("%d
",rank(xx));break;
case 4:printf("%d
",kth(xx));break;
case 5:printf("%d
",pre(xx));break;
case 6:printf("%d
",nxt(xx));break;
}
}
return 0;
}
【2.in】 20 1 964673 5 968705 4 1 3 964673 5 965257 1 915269 1 53283 3 964673 3 53283 3 53283 1 162641 5 973984 1 948119 2 915269 2 53283 6 959161 1 531821 1 967521 2 531821 1 343410 【2.out】 964673 964673 1 964673 3 1 1 964673 964673
【3.in】
50
1 577793
1 408221
1 880861
2 408221
1 460353
1 223489
6 577713
4 2
5 889905
2 880861
1 100033
1 73956
1 22575
5 583761
6 571549
1 812645
4 3
1 643621
1 451623
6 14895
1 556691
4 1
1 225789
2 22575
1 632329
3 73956
1 316785
5 101413
4 11
5 639414
6 636353
1 272382
1 434049
2 643621
1 99617
2 577793
1 921581
1 894033
3 223489
1 767367
3 272382
1 642721
1 272033
3 632329
1 737721
1 864513
5 746457
1 877545
1 51097
1 484817
【3.out】
577793
460353
880861
577793
577793
100033
22575
22575
1
100033
643621
632329
643621
4
6
13
737721
9.LCT
//Twenty
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<queue>
#include<vector>
#define lc ch[x][0]
#define rc ch[x][1]
const int maxn=3*1e5+5;
using namespace std;
int k,tot,n,m,a,b,p[maxn],ch[maxn][2],v[maxn],sum[maxn],flip[maxn];
inline int read(){
int ret=0,f=1; char ch=getchar();
while((ch!='-')&&(ch<'0'||ch>'9')) ch=getchar();
if(ch=='-') f=-1,ch=getchar();
for(;ch>='0'&&ch<='9';ch=getchar()) ret=ret*10+ch-'0';
return ret*f;
}
void update(int x) {sum[x]=v[x]; if(lc)sum[x]^=sum[lc]; if(rc)sum[x]^=sum[rc];}
void down(int x){
if(!flip[x]) return ;
swap(lc,rc);
flip[lc]^=1;
flip[rc]^=1;
flip[x]^=1;
}
bool isroot(int x) {return (ch[p[x]][0]!=x)&&(ch[p[x]][1]!=x);}
void rotate(int x){
int y=p[x],z=p[y],l=(x==ch[y][1]),r=l^1;
if(!isroot(y)) ch[z][y==ch[z][1]]=x; p[x]=z;
ch[y][l]=ch[x][r]; p[ch[x][r]]=y;
ch[x][r]=y; p[y]=x;
update(y); update(x);
}
void splay(int x){
static int s[maxn],top;
s[top=1]=x;
for(int i=x;!isroot(i);i=p[i]) s[++top]=p[i];
while(top) down(s[top--]);
for(;!isroot(x);rotate(x)){
int y=p[x],z=p[y];
if(!isroot(y)){
((x==ch[y][1])^(y==ch[z][1]))?rotate(x):rotate(y);
}
}
}
void access(int x){
for(int t=0;x;x=p[t=x]){
splay(x);
ch[x][1]=t;
update(x);
}
}
int findroot(int x){
access(x);
splay(x);
while(lc) x=lc;
return x;
}
bool lt(int a,int b){
return findroot(a)==findroot(b);
}
void newroot(int x){
access(x);
splay(x);//fasdgggggggggggggggg
flip[x]^=1;
}
void link(int a,int b){
if(lt(a,b)) return;
newroot(a);
p[a]=b;
}
void del(int a,int b){
newroot(a);//splay(a);
access(b);
//if(p[b]==a) ch[a][b==ch[a][1]]=0;
splay(b);//sdgadfffgaggggggggggfjdgfjhfghgf
if(ch[b][0]==a) ch[b][0]=p[a]=0;
}
void change(int a,int b){
splay(a);//newroot(a);
v[a]=b;
update(a);
}
void query(int a,int b){
newroot(a);//splay(a);
access(b);
splay(b);//gdfgfgb gshfthhhhhhhhhhhhhhhhhhhhh
printf("%d
",sum[b]);
}
int main()
{
n=read(); m=read();
for(int i=1;i<=n;i++){
a=read();
v[i]=sum[i]=a;
}
while(m--){
k=read(); a=read(); b=read();
switch(k){
case 0:query(a,b);break;
case 1:link(a,b); break;
case 2:del(a,b); break;
case 3:change(a,b);break;
}
}
return 0;
}
10.左偏树
//Twenty
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<queue>
#include<vector>
#define lc ch[x][0]
#define rc ch[x][1]
const int maxn=100000+299;
using namespace std;
int n,m,k,x,y,ch[maxn][2],fa[maxn],v[maxn],bo[maxn],dis[maxn];
int find(int x){
return x==fa[x]?x:fa[x]=find(fa[x]);
}
int merge(int x,int y){
if(!x) {return y;}
if(!y) {return x;}
if(v[x]>v[y]) swap(x,y);
fa[y]=x;
rc=merge(rc,y);
if(dis[rc]>dis[lc]) swap(lc,rc);
if(!rc) dis[x]=0;
else dis[x]=dis[rc]+1;
return x;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
scanf("%d",&v[i]);
fa[i]=i;
}
while(m--){
scanf("%d%d",&k,&x);
if(k==1){
scanf("%d",&y);
if(!bo[x]&&!bo[y]&&find(x)!=find(y))
x=merge(find(x),find(y));
}
else{
if(bo[x]) cout<<-1<<endl;
else{
x=find(x);
printf("%d
",v[x]);
fa[lc]=lc; fa[rc]=rc;
if(lc&&rc) lc=merge(lc,rc);
if(lc) fa[x]=lc;
else fa[x]=rc;
lc=rc=0;
}
bo[x]=1;
}
}
return 0;
}
11.KD-Tree
//Twenty
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<queue>
#include<vector>
const int maxn=500000+299;
using namespace std;
int ans=1e9+7,now,nowx,nowmax,nowmin,root,y,n,D,data[maxn][2][2],ch[maxn][2];
struct node{
int d[2];
friend bool operator <(const node&A,const node&B){
return A.d[D]<B.d[D];
}
}a[maxn],T;
void update(int x){
for(int i=0;i<2;i++)
for(int j=0;j<2;j++)
data[x][i][j]=a[x].d[i];
for(int i=0;i<2;i++)
if(y=ch[x][i])
for(int j=0;j<2;j++){
data[x][j][0]=min(data[x][j][0],data[y][j][0]);
data[x][j][1]=max(data[x][j][1],data[y][j][1]);
}
}
int build(int l,int r,int k){
if(l>r) return 0;
int mid=(l+r)>>1;
D=k;
nth_element(a+l,a+mid,a+r+1);
ch[mid][0]=build(l,mid-1,k^1);
ch[mid][1]=build(mid+1,r,k^1);
update(mid);
return mid;
}
int max_dis(int x){
if(!x) return -1e9;
int res=0;
for(int i=0;i<2;i++)
res+=max(abs(T.d[i]-data[x][i][0]),abs(data[x][i][1]-T.d[i]));
return res;
}
int dis(int x){
return abs(a[x].d[0]-T.d[0])+abs(a[x].d[1]-T.d[1]);
}
int min_dis(int x){
if(!x) return 1e9;
int res=0;
for(int i=0;i<2;i++)
res+=max(T.d[i]-data[x][i][1],0);
for(int i=0;i<2;i++)
res+=max(data[x][i][0]-T.d[i],0);
return res;
}
void qrymin(int x){
if(!x) return;
if(x!=nowx) nowmin=min(dis(x),nowmin);
int lc=ch[x][0],rc=ch[x][1];
int l=min_dis(lc);
int r=min_dis(rc);
if(l>r) {swap(lc,rc);swap(l,r);}
if(lc&&l<nowmin) qrymin(lc);
if(rc&&r<nowmin) qrymin(rc);
}
void qrymax(int x){
if(!x) return;
if(x!=nowx) nowmax=max(dis(x),nowmax);
int lc=ch[x][0],rc=ch[x][1];
int l=max_dis(lc);
int r=max_dis(rc);
if(l<r) {swap(lc,rc);swap(l,r);}
if(lc&&l>nowmax) qrymax(lc);
if(rc&&r>nowmax) qrymax(rc);
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d%d",&a[i].d[0],&a[i].d[1]);
root=build(1,n,0);
for(int i=1;i<=n;i++){
nowx=i;
T=a[i];
nowmax=-1e9+7;
nowmin=1e9+7;
qrymin(root);
qrymax(root);
ans=min(ans,nowmax-nowmin);
}
printf("%d
",ans);
return 0;
}
12.分块
//Twenty
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<algorithm>
const int maxn=200000+10;
using namespace std;
int n,m,k,gs,ks;
int a[maxn],b[maxn],c[450][maxn],l,r,v;
char qu[10];
int main()
{
ios::sync_with_stdio(false);
cin>>n>>m>>k;
ks=floor(sqrt(n));
if(n%ks==0) gs=n/ks; else gs=n/ks+1;
for(int i=1;i<=n;i++)cin>>a[i];
for(int i=1;i<=ks;i++)
for(int j=1;j<=gs;j++)
{
int num=(i-1)*gs+j;
c[i][a[num]%k]++;
}
while(m--){
cin>>qu>>l>>r;
int lx,rx,ans;
ans=0;
lx=(l-1)/gs+1;
rx=(r-1)/gs;
if(qu[0]=='c'){
if(rx<lx)
{for(int i=l;i<=r;i++)
if((a[i]+b[i])%k==0)ans++;}
else {
for(int i=l;i<=lx*gs;i++)
if((a[i]+b[lx])%k==0)ans++;
for(int i=lx+1;i<=rx;i++)
ans+=c[i][(k-b[i]%k)%k];
for(int i=rx*gs+1;i<=r;i++)
if((a[i]+b[rx+1])%k==0)ans++;
}
cout<<ans<<endl;
}
else {
cin>>v;
if(rx<lx)
{
for(int i=l;i<=r;i++)
{
c[lx][a[i]%k]--;
a[i]+=v;
c[lx][a[i]%k]++;
}
}
else {
for(int i=l;i<=lx*gs;i++)
{
c[lx][a[i]%k]--;
a[i]+=v;
c[lx][a[i]%k]++;
}
for(int i=lx+1;i<=rx;i++)
b[i]+=v;
for(int i=rx*gs+1;i<=r;i++)
{
c[rx][a[i]%k]--;
a[i]+=v;
c[rx][a[i]%k]++;
}
}
}
}
return 0;
}
13.树套树
//Twenty
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<queue>
#include<vector>
#define lc x<<1
#define rc x<<1|1
#define mid ((l+r)>>1)
const int maxn=10005;
bool st;
int tot,T,ql,qr,qq,aa[maxn],n,m,sg[maxn<<2],ls[maxn*450],rs[maxn*450],sgq[maxn*450],que[maxn];
int nn=1e9;
char qs[5];
bool ed;
using namespace std;
inline int read() {
int res=0;char ch=getchar();
while(ch<'0'||ch>'9') ch=getchar();
for(;ch>='0'&&ch<='9';ch=getchar()) res=res*10+ch-'0';
return res;
}
void buq(int &x,int l,int r,int v,int kk){
if(!x) x=++tot;
if(l==r) {if(kk) sgq[x]++; else sgq[x]--; return;}
if(v<=mid) buq(ls[x],l,mid,v,kk);
else buq(rs[x],mid+1,r,v,kk);
sgq[x]=sgq[ls[x]]+sgq[rs[x]];
}
void build(int x,int l,int r){
for(int i=l;i<=r;i++) buq(sg[x],1,nn,aa[i],1);
if(l==r) return;
build(lc,l,mid); build(rc,mid+1,r);
}
void change(int x,int l,int r,int xw,int jv,int xv){
buq(sg[x],1,nn,jv,0); buq(sg[x],1,nn,xv,1);
if(l==r) return;
if(xw<=mid) change(lc,l,mid,xw,jv,xv);
else change(rc,mid+1,r,xw,jv,xv);
}
void query(int x,int l,int r,int ql,int qr){
if(l>=ql&&r<=qr) {que[++que[0]]=sg[x];return;}
if(qr<=mid) query(lc,l,mid,ql,qr);
else if(ql>mid) query(rc,mid+1,r,ql,qr);
else {query(lc,l,mid,ql,qr); query(rc,mid+1,r,ql,qr);}
}
int qry(int ql,int qr,int k){
que[0]=0;
query(1,1,n,ql,qr);
int l=1,r=nn;
for(;;){
int now=0;
for(int i=1;i<=que[0];i++)
now+=sgq[ls[que[i]]];
if(now>=k) {
for(int i=1;i<=que[0];i++)
que[i]=ls[que[i]];
r=mid;
}
else{
for(int i=1;i<=que[0];i++)
que[i]=rs[que[i]];
k-=now;
l=mid+1;
}
if(l==r) return l;
}
}
int main()
{
//printf("%d
",(&ed-&st)/1024/1024);
//for(;;);
//freopen("dynamic9.in","r",stdin);
//freopen("aa.out","w",stdout);
/*scanf("%d",&T);
while(T--){*/
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) {aa[i]=read(); aa[i]++; }
/*sort(aa+1,aa+n+1);
nn=unique(aa+1,aa+n+1)-(aa+1);*/
//for(int i=1;i<=n;i++) {bb[i]=lower_bound(aa+1,aa+n+1,bb[i])-aa;}
build(1,1,n);
while(m--){
scanf("%s",qs);
ql=read(); qr=read();
if(qs[0]=='C'){
qr++;
change(1,1,n,ql,aa[ql],qr);
aa[ql]=qr;
}
else{
qq=read();//scanf("%d",&qq);
printf("%d
",qry(ql,qr,qq)-1);
}
}
/*if(T){
tot=0;
memset(aa,0,sizeof(aa));
memset(sg,0,sizeof(sg));
memset(sgq,0,sizeof(sgq));
memset(ls,0,sizeof(ls));
memset(rs,0,sizeof(rs));
}
}*/
return 0;
}
树套树
//Twenty
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<vector>
#include<cstdio>
#include<cmath>
#include<queue>
#include<ctime>
#define inf 1e8+1
const int maxn=1e5+5;
typedef long long LL;
using namespace std;
int n,T,a[maxn];
template<typename T> void read(T &x) {
char ch=getchar(); T f=1; x=0;
while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
if(ch=='-') f=-1,ch=getchar();
for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f;
}
int tot,ls[maxn*100],rs[maxn*100],val[maxn*100];
#define lc ls[x]
#define rc rs[x]
#define mid ((l+r)>>1)
int sqry(int x,int l,int r,int ql,int qr) {
if(!x) return 0;
if(l>=ql&&r<=qr) return val[x];
if(qr<=mid) return sqry(lc,l,mid,ql,qr);
else if(ql>mid) return sqry(rc,mid+1,r,ql,qr);
return sqry(lc,l,mid,ql,qr)+sqry(rc,mid+1,r,ql,qr);
}
void update(int &x,int l,int r,int v,int f) {
if(!x) x=++tot;
if(l==r) {val[x]+=f; return;}
if(v<=mid) update(lc,l,mid,v,f);
else update(rc,mid+1,r,v,f);
val[x]=val[lc]+val[rc];
}
int rt[maxn];
void change(int x,int y,int o) {
for(int i=x;i<=n;i+=(i&(-i))) {
if(!o) update(rt[i],1,inf,a[x],-1);
update(rt[i],1,inf,y,1);
}
a[x]=y;
}
int qry(int l,int r,int ql,int qr) {
int res1=0,res2=0;
for(int i=r;i;i-=(i&(-i)))
res1+=sqry(rt[i],1,inf,ql,qr);
for(int i=l-1;i>0;i-=(i&(-i)))
res2+=sqry(rt[i],1,inf,ql,qr);
return res1-res2;
}
int q1[maxn],h=1,t,q2[maxn],hh=1,tt;
int kth(int l,int r,int k) {
h=hh=1; t=tt=0;
int res=0;
for(int i=r;i;i-=(i&(-i)))
if(rt[i]&&val[rt[i]]) q1[++t]=rt[i];
for(int i=l-1;i>0;i-=(i&(-i)))
if(rt[i]&&val[rt[i]]) q2[++tt]=rt[i];
int ll=1,rr=inf;
while(ll!=rr) {
int ans1=0,ans2=0;
for(int i=h;i<=t;i++)
ans1+=val[ls[q1[i]]];
for(int i=hh;i<=tt;i++)
ans2+=val[ls[q2[i]]];
int prt=t,prh=h;
for(int i=prh;i<=prt;i++) {
if(ans1-ans2>=k) {
if(ls[q1[i]]&&val[ls[q1[i]]]) q1[++t]=ls[q1[i]];
}
else
if(rs[q1[i]]&&val[rs[q1[i]]]) q1[++t]=rs[q1[i]];
}
if(prt) h=prt+1;
prt=tt; prh=hh;
for(int i=prh;i<=prt;i++) {
if(ans1-ans2>=k) {
if(ls[q2[i]]&&val[ls[q2[i]]]) q2[++tt]=ls[q2[i]];
}
else
if(rs[q2[i]]&&val[rs[q2[i]]]) q2[++tt]=rs[q2[i]];
}
if(prt) hh=prt+1;
if(ans1-ans2<k) {
ll=(ll+rr)/2+1;
k-=(ans1-ans2);
}
else rr=(ll+rr)/2;
}
return ll;
}
void pre(int x,int l,int r) {
int rk=qry(l,r,1,x-1);
if(rk<1) {
printf("-2147483647
");
return;
}
printf("%d
",kth(l,r,rk)-1);
}
void nxt(int x,int l,int r) {
int rk=qry(l,r,1,x-1)+1;
int fl=qry(l,r,x,x);
if(fl) rk++;
if(rk>r-l+1) {
printf("2147483647
");
return;
}
printf("%d
",kth(l,r,rk)-1);
}
int main() {
srand(time(0));
read(n);
read(T);
for(register int i=1;i<=n;i++) {
read(a[i]); a[i]++;
change(i,a[i],1);
}
while(T--) {
int o,l,r,k,pos,x;
read(o);
if(o==3) {
read(pos);
read(x); x++;
change(pos,x,0);
}
else {
read(l);
read(r);
read(k); if(o!=2) k++;
if(o==1) printf("%d
",qry(l,r,1,k-1)+1);
else if(o==2) printf("%d
",kth(l,r,k)-1);
else if(o==4) pre(k,l,r);
else if(o==5) nxt(k,l,r);
}
}
return 0;
}
14.可持久化平衡树
//Twenty
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<vector>
#include<cstdio>
#include<cmath>
#include<queue>
#include<ctime>
typedef long long LL;
using namespace std;
const int maxn=1e6+7;
int n,tot,rt[maxn],ch[maxn*25][2],v[maxn*25],hr[maxn*25],sz[maxn*25];
template<typename T> void read(T &x) {
char ch=getchar(); T f=1; x=0;
while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
if(ch=='-') f=-1,ch=getchar();
for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f;
}
#define lc ch[x][0]
#define rc ch[x][1]
void update(int x) {sz[x]=sz[lc]+sz[rc]+1;}
void create(int &x,int y) {
x=++tot;
v[x]=y;
lc=rc=0;
sz[x]=1;
hr[x]=rand();
}
void copy(int x,int y) {
v[x]=v[y];
lc=ch[y][0];
rc=ch[y][1];
sz[x]=sz[y];
hr[x]=hr[y];
}
int merge(int x,int y) {
if(!(x*y)) return x^y;
int t=++tot;
if(hr[x]<hr[y]) {
copy(t,x);
ch[t][1]=merge(ch[t][1],y);
}
else {
copy(t,y);
ch[t][0]=merge(x,ch[t][0]);
}
update(t);
return t;
}
#define pr pair<int,int>
#define se second
#define fi first
pr split(int x,int k) {
if(!x) return make_pair(0,0);
int t=++tot;
copy(t,x);
pr p;
if(sz[lc]>=k) {
p=split(ch[t][0],k);
ch[t][0]=p.se; p.se=t;
}
else {
p=split(ch[t][1],k-sz[lc]-1);
ch[t][1]=p.fi; p.fi=t;
}
update(t);
return p;
}
int rank(int root,int y) {
int res=1;
for(int x=root;x;) {
if(v[x]<y) res+=(sz[lc]+1),x=rc;
else x=lc;
}
return res;
}
int kth(int root,int k) {
for(int x=root;x;) {
if(sz[lc]+1==k) return v[x];
if(sz[lc]+1<k) {k-=(sz[lc]+1); x=rc;}
else x=lc;
}
}
int exist(int root,int y) {
int res=0;
for(int x=root;x;) {
if(v[x]==y) {res=1; break;}
if(v[x]<y) x=rc;
else x=lc;
}
return res;
}
void pre(int root,int y) {
int res=-1;
for(int x=root;x;) {
if(v[x]<y) res=v[x],x=rc;
else x=lc;
}
if(res==-1) printf("-2147483647
");
else printf("%d
",res);
}
void nxt(int root,int y) {
int res=-1;
for(int x=root;x;) {
if(v[x]>y) res=v[x],x=lc;
else x=rc;
}
if(res==-1) printf("2147483647
");
else printf("%d
",res);
}
void insert(int &x,int y) {
int rk=rank(x,y)-1;
pr p=split(x,rk);
int z; create(z,y);
x=merge(merge(p.fi,z),p.se);
}
void del(int &x,int y) {
if(!exist(x,y)) return;
int rk=rank(x,y)-1;
pr p=split(x,rk);
pr tp=split(p.se,1);
x=merge(p.fi,tp.se);
}
int main() {
srand(time(0));
int lst,o,x;
read(n);
for(int i=1;i<=n;i++) {
read(lst);
read(o);
read(x);
rt[i]=rt[lst];
switch(o) {
case 1:insert(rt[i],x);break;
case 2:del(rt[i],x);break;
case 3:printf("%d
",rank(rt[i],x));break;
case 4:printf("%d
",kth(rt[i],x));break;
case 5:pre(rt[i],x);break;
case 6:nxt(rt[i],x);break;
}
}
return 0;
}
---------------------------------- 17-11-3------------------------------------
终于把洛谷模板刷完啦!撒花~