甜甜圈(树状数组)(线段树)

甜甜圈(树状数组)(线段树)文章目录1.树状数组维护2.线段树维护题目描述艾洛喜欢吃甜食,他有n个甜甜圈,现在叠成了两叠(如下图所示),第一叠有n1n1n1个,第二叠有n2n2n2个(n1+n2=n)(n1+n2=n)(n1+n2=n),要解决的


题目描述

艾洛喜欢吃甜食,他有n个甜甜圈,现在叠成了两叠(如下图所示),第一叠有
n 1 n1 n1个,第二叠有
n 2 n2 n2
( n 1 + n 2 = n ) (n1+n2=n) (n1+n2=n),要解决的问题如下:

  • ​ 每个甜甜圈都有一个唯一的甜度值 s i s_i si,甜度值两两不同;
  • ​ 每次艾洛可以把任意一叠位于顶端的一个甜甜圈移动到另一叠顶端,若该甜甜圈是当前所有甜甜圈中最甜的(甜度值最大),那么艾洛不会移动甜甜圈,而是直接吃掉;

请你求出艾洛吃完所有甜甜圈的最小移动步数;

在这里插入图片描述

输入描述:

第一行,两个正整数 n 1 , n 2 ( 1 ≤ n 1 + n 2 ≤ 100000 ) n1,n2 (1≤n1+n2≤100000) n1,n2(1n1+n2100000),分别表示两叠甜甜圈的个数。
第二行, n 1 n1 n1个整数,按从顶到底的顺序排列,表示第一叠甜甜圈的甜度值。
第三行, n 2 n2 n2个整数,按从顶到底的顺序排列,表示第二叠甜甜圈的甜度值。
保证 1 ≤ s i ≤ 6 ∗ 1 0 6 1≤si≤6∗10^6 1si6106且两两互不相同。

输出描述:

总共一行,一个整数,表示最少步数。

输入

3 3
1 4 5
2 7 3

输出

6
1. 树状数组维护
#include <bits/stdc++.h>
using namespace std;
#define MAIN signed main()
#define int long long 
const int maxn = 1e5+5;

struct Node { 
   
	int v,pos;
}a[maxn*2];

int C[maxn*2]; //树状数组
int n;
int query(int i)
{ 
   
	int ans = 0;
	while(i > 0)
	{ 
   
		ans += C[i];
		i -= i & -i;
	}
	return ans;
}

void update(int i,int x)
{ 
   
	while(i <= n)
	{ 
   
		C[i] += x;
		i += i & -i;
	}
}

MAIN
{ 
   
	int n1,n2;
	scanf("%lld%lld",&n1,&n2);
	n = n1 + n2;
	for(int i=n1;i>=1;--i) //反向存储 
	{ 
   
		scanf("%lld",&a[i].v);
		a[i].pos = i;
		update(i,1);
	}
	for(int i=n1+1;i<=n1+n2;++i) //正向存储 Value and index 
	{ 
   
		scanf("%lld",&a[i].v);
		a[i].pos = i;
		update(i,1);
	}
	
	sort(a+1,a+n+1,[](Node a,Node b){ 
   
		return a.v > b.v;
	});
	
	int p = a[1].pos;//分界线 
	update(a[1].pos,-1);
	int res = p > n1 ? (p - n1 - 1): (n1 - p);
	for(int i=2;i<=n;++i)
	{ 
   
		update(a[i].pos,-1);//减去1 变0 
		int q = abs(query(a[i].pos) - query(p)); //query
		res += q;
		p = a[i].pos;
	}
	printf("%lld\n",res);
	return 0;
}
2.线段树维护
#include <bits/stdc++.h>
using namespace std;
#define MAIN signed main()
#define int long long 
const int maxn = 1e5+5;

int n;

struct Node { 
   
	int v,pos;
}a[maxn*2];

struct tree{ 
   
    int l ,r;
    int v;
}tr[maxn*8];

void pushup(int u)
{ 
   
    tr[u].v = tr[u<<1].v + tr[u<<1|1].v;
}

void build(int u,int l,int r)
{ 
   
    tr[u] = { 
   l,r};
    if(l == r)
    { 
   
    	tr[u] = { 
   l,r,1};
    	return;
	}
    int mid = l + r >> 1;
    build(u<<1,l,mid);
    build(u<<1|1,mid+1,r);
    pushup(u); 
}

void modify(int u,int x,int v)
{ 
   
    if(tr[u].l==x && tr[u].r == x){ 
   
        tr[u].v = v;
        return;
    }
    int mid = tr[u].l + tr[u].r >> 1;
    if(x <= mid) modify(u<<1,x,v);
    else modify(u<<1|1,x,v);
    pushup(u);
}
///查询一个区间的属性
int query(int u,int l,int r)
{ 
   
	if(l > r) swap(l,r);
    if(l <= tr[u].l && tr[u].r <= r)
        return tr[u].v;
    int mid = tr[u].l + tr[u].r >> 1;
    int res = 0;
	if(l <= mid) res +=query(u<<1,l,r);
    if(r >  mid) res += query(u<<1|1,l,r);
    return res;
}


MAIN
{ 
   
	int n1,n2;
	scanf("%lld%lld",&n1,&n2);
	n = n1 + n2;
	build(1,1,n);
	for(int i=n1;i>=1;--i) //反向存储 
	{ 
   
		scanf("%lld",&a[i].v);
		a[i].pos = i;
		modify(1,i,1);
	}
	for(int i=n1+1;i<=n1+n2;++i) //正向存储 Value and index 
	{ 
   
		scanf("%lld",&a[i].v);
		a[i].pos = i;
		modify(1,i,1);
	}
	
	sort(a+1,a+n+1,[](Node a,Node b){ 
   
		return a.v > b.v;
	});
	
	int p = a[1].pos;//分界线 
	modify(1,a[1].pos,0);
	int res = p > n1 ? (p - n1 - 1): (n1 - p);
	for(int i=2;i<=n;++i)
	{ 
   
		modify(1,a[i].pos,0);//减去1 变0 
		int q = abs(query(1,a[i].pos,p)); //query
		res += q;
		p = a[i].pos;
	}
	printf("%lld\n",res);
	return 0;
}

今天的文章甜甜圈(树状数组)(线段树)分享到此就结束了,感谢您的阅读。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/61316.html

(0)
编程小号编程小号

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注