• 作业(?)


    我写了几颗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<<'
    ';
    			merge(rt,a,b);
    		}
    		if(opt==4)
    		{
    			cout<<kth(x)<<'
    ';
    		}
    		if(opt==5)
    		{
    			int a=0,b=0;
    			split(rt,a,b,x-1);
    			cout<<mx(a)<<'
    ';
    			merge(rt,a,b);
    		}
    		if(opt==6)
    		{
    			int a=0,b=0;
    			split(rt,a,b,x);
    			cout<<mi(b)<<'
    ';
    			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]<<'
    ';
    			merge(a,a,b);
    			merge(rt,a,c);
    		}
    	}
    	return 0;
    }
    

    两个同样长度有序数列的合并, 合并后的数列中的每一个元素都是从这两个数列中分别选出一个数相加得到的(同时它也是有序的),求合并后的数列前几个数。

    当然,也可以扩展到多个有序表的合并, 两两合并即可(想一想,为什么 , 假设前k-1个有序表的合并结果是有序表S,那么S和第k个有序表的合并结果P的前几项必定是由S的前几项中的某些数和第k个有序表中的某些数组成的)

    代码如下

    //Rujia Liu 写哒, 不过我抄也没好好抄qwq
    struct Item {
    	int s,b; //s=A[x] + B[b]
    	Item(int s,int b):s(s), b(b) {} 
    	bool operator < (const Item& rhs) const {
    		return s > rhs.s;
    	}
    };
    
    void merge(int* A,int *B,int *C,int n) {
    	priority_queue<Item> pq;
    	for(int i=0;i<n;++i)
    		q.push(Item(A[i] + B[0], 0));
    	for(int i=0;i<n;++i) {
    		Item item = q.top(); q.pop();
    		C[i] = item.s;
    		int b=item.b;
    		if(b+1<n) q.push(Item(item.s-B[b]+B[b+1], b+1));
    	}
    }
    

    //LA 3027 基本带权并查集的维护
    //代码来自 Rujia Liu
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    
    const int maxn = 20000 + 10;
    int pa[maxn], d[maxn];
    
    int findset( int x )
    {
    	if(pa[x] != x) {
    		int root = findset( pa[x] );
    		d[x] += d[ pa[x] ];
    		return pa[x] = root;
    	} else return x;
    }
    
    int main() {
    	int T; scanf("%d", &T);
    	while(T--) {
    		int n, u, v;
    		char cmd[9];
    		scanf("%d", &n);
    		for(int i=1;i<=n;++i) { pa[i] = i; d[i] = 0; }
    		// init
    		while( scanf("%s", cmd) && cmd[0] != 'O' ) {
    			if(cmd[0] == 'E') { scanf("%d", &u); findset(u); printf("%d
    ", &d[u]); }
    			if(cmd[0] == 'I') { scanf("%d%d", &u, &v); pa[u] = v; d[u] = abs(u-v) % 1000; }
    		}
    	}
    	return 0;
    }
    

    //某意义不明的树状数组
    #include<bits/stdc++.h>
    using namespace std;
    const int maxn = 1000005;
    
    int a[maxn], n;
    int t[maxn], l[maxn], r[maxn];
    
    inline int lowbit(int x) { return x & -x; }
    
    int qy(int x)
    {
    	int res=0;
    	for(;x;x-=lowbit(x)) res+=t[x];
    	return res;
    }
    
    int ins(int x)
    {
    	for(;x<=n;x+=lowbit(x)) t[x] += 1;
    }
    
    int main() {
    	scanf("%d", &n);
    	for(int i=1;i<=n;++i) scanf("%d", &a[i]);
    	
    	for(int i=1;i<=n;++i)
    	{
    		l[i] = qy(a[i]-1);
    		ins(a[i]);
    	}
    	memset(t,0,sizeof t);
    	for(int i=n;i>=1;--i)
    	{
    		r[i] = qy(a[i]-1);
    		ins(a[i]);
    	}
    	
    	long long ans=0;
    	for(int i=1;i<=n;++i)
    		ans += (long long)l[i]*(n-i-r[i]) + (long long)r[i]*(a-1-l[i]);
    	cout << ans;
    	return 0;
    }
    
    
    //对序列游程编码
    for(int i=1;i<=n;++i)
    scanf("%d", &a[i]);
    			
    m = 0, pre = 0;
    for(int i=1;i<=n;++i)
    if(a[i] != a[i+1])
    {
    	b[++m] = a[i];
    	siz[m] = i - pre;
    	pre = i;
    }
    
    //单调不降序列的静态区间众数问题
    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=100005;
    
    int n,m,q;
    int a[maxn];
    
    int b[maxn], siz[maxn];
    
    int d[21][maxn];
    int pos[maxn], l[maxn], r[maxn];
    void init()
    {
    	int L=1;
    	for(int i=1;i<=m;++i)
    	{
    		l[i] = L;
    		r[i] = L + siz[i] - 1;
    		for(int j=l[i];j<=r[i];++j) pos[j] = i;
    		L = r[i] + 1;
    	}
    	
    	for(int i=1;i<=m;++i) d[0][i] = siz[i];
    	for(int k=1;k<=20;++k)
    		for(int i=1;i+(1<<k)-1<=n;++i)
    			d[k][i] = max(d[k-1][i], d[k-1][i+(1<<(k-1))]);
    }
    
    int rmq(int L,int R)
    {
    	if(L>R) return 0;
    	int k=log2(R-L+1);
    	return max(d[k][L], d[k][R-(1<<k)+1]);
    }
    
    int calc(int L,int R)
    {
    	return R-L+1;
    }
    
    int main()
    {
    	int pre;
    	while(scanf("%d", &n) && n)
    	{
    		scanf("%d", &q);
    		for(int i=1;i<=n;++i)
    			scanf("%d", &a[i]);
    			
    		m = 0, pre = 0;
    		for(int i=1;i<=n;++i)
    		if(a[i] != a[i+1])
    		{
    			b[++m] = a[i];
    			siz[m] = i - pre;
    			pre = i;
    		}
    		
    		init();
    		
    		int L,R;
    		while(q--)
    		{
    			scanf("%d%d", &L, &R);
    			if(pos[L] == pos[R])
    			{
    				cout << calc(L,R) << '
    ';
    				continue;
    			}
    			int ans = rmq(pos[L]+1, pos[R]-1);
    			ans = max( ans, calc(L, r[pos[L]]) );
    			ans = max( ans, calc(l[pos[R]], R) );
    			cout << ans << '
    ';
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    我爱Java系列之---【SpringBoot打成war包部署】
    279. Perfect Squares
    矩阵dfs--走回路
    112. Path Sum
    542. 01 Matrix
    106. Construct Binary Tree from Inorder and Postorder Traversal
    105. Construct Binary Tree from Preorder and Inorder Traversal
    Invert Binary Tree
    563 Binary Tree Tilt
    145 Binary Tree Postorder Traversal
  • 原文地址:https://www.cnblogs.com/tztqwq/p/12070177.html
Copyright © 2020-2023  润新知