zoukankan      html  css  js  c++  java
  • 作业(?)

    我写了几颗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;
    }
    
  • 相关阅读:
    最小二乘拟合(scipy实现)
    接口实例
    类的继承:员工和老板
    设计模式(Design Patterns)
    创建类
    面向对象1
    java随机数:彩票抽奖 + 验证码
    判断字符串中字符出现的次数+去除空格
    输出二维数组所有元素的和
    输出 一维数组中最大的数+数组遍历
  • 原文地址:https://www.cnblogs.com/tztqwq/p/12070177.html
Copyright © 2011-2022 走看看