我写了几颗fhq treap, 用它们解决了洛谷上的三个模板题 : 普通平衡树、 文艺平衡树、 线段树1.
//普通平衡树
#include<bits/stdc++.h>
using namespace std;
const int maxn=100005;
int tot,ls[maxn],rs[maxn],val[maxn],rnd[maxn],siz[maxn];
int rt;
int newnode(int weight)
{
val[++tot]=weight;
rnd[tot]=rand();
siz[tot]=1;
return tot;
}
void update(int k)
{
siz[k] = 1 + siz[ls[k]] + siz[rs[k]];
}
void merge(int &k,int a,int b)
{
if(!a||!b) {
k=a+b;
return;
}
if(rnd[a] < rnd[b])
{
k=a;
merge(rs[a], rs[a], b);
}
else
{
k=b;
merge(ls[b], a, ls[b]);
}
update(k);
}
void split(int k,int &a,int &b,int weight)
{
if(!k)
{
a=b=0;
return;
}
if(val[k] <= weight)
{
a=k;
split(rs[a], rs[a], b, weight);
}
else
{
b=k;
split(ls[b], a, ls[b], weight);
}
update(k);
}
int kth(int k)
{
int p=rt;
while(1)
{
if(siz[ls[p]] + 1 == k) return val[p];
else
if(siz[ls[p]] + 1 < k) k-=siz[ls[p]]+1, p=rs[p];
else
p=ls[p];
}
}
int mx(int p)
{
while(rs[p]) p=rs[p];
return val[p];
}
int mi(int p)
{
while(ls[p]) p=ls[p];
return val[p];
}
int main()
{
srand((unsigned)time(0));
int n; cin >> n;
while(n--)
{
int opt,x; scanf("%d%d",&opt,&x);
if(opt==1)
{
int a=0,b=0,nnode=newnode(x);
split(rt,a,b,x);
merge(a,a,nnode);
merge(rt,a,b);
}
if(opt==2)
{
int a=0,b=0,c=0;
split(rt,b,c,x);
split(b,a,b,x-1);
merge(b,ls[b],rs[b]);
merge(a,a,b);
merge(rt,a,c);
}
if(opt==3)
{
int a=0,b=0;
split(rt,a,b,x-1);
cout<<siz[a]+1<<'\n';
merge(rt,a,b);
}
if(opt==4)
{
cout<<kth(x)<<'\n';
}
if(opt==5)
{
int a=0,b=0;
split(rt,a,b,x-1);
cout<<mx(a)<<'\n';
merge(rt,a,b);
}
if(opt==6)
{
int a=0,b=0;
split(rt,a,b,x);
cout<<mi(b)<<'\n';
merge(rt,a,b);
}
}
return 0;
}
//文艺平衡树
#include<bits/stdc++.h>
using namespace std;
const int maxn=100005;
int n,m;
int rnd[maxn],tag[maxn],ls[maxn],rs[maxn],siz[maxn],val[maxn];
int rt;
int newnode(int x)
{
val[x]=x; siz[x]=1; rnd[x]=rand();
return x;
}
void update(int k)
{
siz[k] = 1 + siz[ls[k]] + siz[rs[k]];
}
void pushdown(int k)
{
swap(ls[k], rs[k]);
tag[k]=0;
tag[ls[k]] ^= 1;
tag[rs[k]] ^= 1;
}
void merge(int &k,int a,int b)
{
if(!a||!b) {
k=a+b;
return;
}
if(rnd[a]<rnd[b])
{
k=a;
if(tag[a]) pushdown(a);
merge(rs[a],rs[a],b);
}
else
{
k=b;
if(tag[b]) pushdown(b);
merge(ls[b],a,ls[b]);
}
update(k);
}
void split(int k,int &a,int &b,int weight)
{
if(!k) {
a=b=0;
return;
}
if(tag[k]) pushdown(k);
if(siz[ls[k]] + 1 <= weight)
{
a=k;
split(rs[a],rs[a],b,weight-siz[ls[a]]-1);
}
else
{
b=k;
split(ls[b],a,ls[b],weight);
}
update(k);
}
void mid(int k)
{
if(!k) return;
if(tag[k]) pushdown(k);
mid(ls[k]);
cout<<val[k]<<' ';
mid(rs[k]);
}
int main()
{
srand((unsigned)time(0));
cin >> n >> m;
for(int i=1;i<=n;++i)
{
int nnode=newnode(i);
merge(rt,rt,nnode);
}
while(m--)
{
int l,r; scanf("%d%d",&l,&r);
int a=0,b=0,c=0;
split(rt,b,c,r);
split(b,a,b,l-1);
tag[b]^=1;
merge(b,b,c);
merge(rt,a,b);
}
mid(rt);
return 0;
}
//线段树1
#include<bits/stdc++.h>
using namespace std;
const int maxn=100005;
int ls[maxn],rs[maxn],siz[maxn],rnd[maxn];
long long val[maxn],sum[maxn],tag[maxn];
int tot,rt;
int newnode(long long v)
{
val[++tot]=v; sum[tot]=v; rnd[tot]=rand(); siz[tot]=1; return tot;
}
void update(int k)
{
siz[k] = siz[ls[k]] + siz[rs[k]] + 1;
sum[k] = sum[ls[k]] + sum[rs[k]] + val[k];
}
//lazy tag
void ad(int k,long long v)
{
val[k] += v;
sum[k] += siz[k] * v;
}
void pushdown(int k)
{
ad(ls[k], tag[k]); tag[ls[k]] += tag[k];
ad(rs[k], tag[k]); tag[rs[k]] += tag[k];
tag[k]=0;
}
//
void merge(int &k,int a,int b)
{
if(!a||!b) {
k=a+b;
return;
}
if(rnd[a] < rnd[b])
{
k=a;
if(tag[a]) pushdown(a);
merge(rs[a], rs[a], b);
}
else
{
k=b;
if(tag[b]) pushdown(b);
merge(ls[b], a, ls[b]);
}
update(k);
}
void split(int k,int &a,int &b,int weight)
{
if(!k) {
a=b=0;
return;
}
if(tag[k]) pushdown(k);
if(siz[ls[k]] + 1 <= weight)
{
a=k;
split(rs[a], rs[a], b, weight - siz[ls[a]] - 1);
}
else
{
b=k;
split(ls[b], a, ls[b], weight);
}
update(k);
}
int main()
{
int n,m; scanf("%d%d",&n,&m);
for(int i=1;i<=n;++i)
{
long long x; scanf("%lld", &x);
int nnode=newnode(x);
merge(rt,rt,nnode);
}
while(m--)
{
int opt,l,r;
scanf("%d%d%d",&opt, &l, &r);
if(opt==1)
{
long long k; scanf("%lld",&k);
int a=0,b=0,c=0;
split(rt,b,c,r);
split(b,a,b,l-1);
ad(b,k); tag[b]+=k;
merge(a,a,b);
merge(rt,a,c);
}
else
{
int a=0,b=0,c=0;
split(rt,b,c,r);
split(b,a,b,l-1);
cout<<sum[b]<<'\n';
merge(a,a,b);
merge(rt,a,c);
}
}
return 0;
}