线段树专题#2_蒟蒻训练历程记录_HDU5775

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<vector>
#include<map>
#include<algorithm>
#include<queue>
#include<stack>//线段树单点更新查询 
using namespace std;
typedef long long ll;
#define N 100010
int g[4*N];
typedef struct A{
	int w;
	int pos1;
	int add;
}A;
A a[N]; 

bool cmp(A a, A b)
{
	return a.w < b.w;
}

void init(int rt, int l , int r)//递归建立线段树 
{
	if(l == r)
	{
		g[rt] = 0;
		return;
	} 
	int mid = (l+r) >> 1;
	init(rt<<1, l, mid);
	init(rt<<1|1, mid+1, r);
	g[rt] = 0;
} 

int find(int rt, int l, int r, int L, int R)//递归查询 
{
	if(l >= L && r <= R)
	{
		return g[rt];
	}
	int k1 = 0, k2 = 0;
	int mid = (l+r) >> 1;
	if(mid >= L)//这个地方区间要跟所查询的总区间相比较而不是目前查询的区间 
	{
		k1 = find(rt<<1, l, mid, L, R);
	}
	if(mid < R)
	{
		k2 = find(rt<<1|1, mid+1, r, L, R);
	}
	return k1+k2;
} 

void update(int rt, int l, int r, int x)//要记住一直更新的都是现在的根节点。。 
{
	if(l == r && l == x)
	{
		g[rt]++;
		return;
	}
	int mid = (l+r) >> 1;
	if(x <= mid)//这回是拿查找的值跟mid作比较 
	{
		update(rt<<1, l, mid, x);
		g[rt]++;//这个地方更新错了。。 
	}
	if(mid < x)
	{
		update(rt<<1|1, mid+1, r, x);
		g[rt]++;
	}
}

int main()
{
	int t, num = 0;
	scanf("%d", &t);
	while(t--)
	{
		int n;
		scanf("%d", &n);
		for(int i = 1; i <= n; i++)
		{
			scanf("%d", &a[i].w);
			a[i].pos1 = i;
		}
		init(1, 1, n);//初始化建树 
		for(int i = n; i >= 1; i--)
		{
			if(a[i].w == 1)
			   a[i].add = 0;
			else
			   a[i].add = find(1, 1, n, 1, a[i].w-1);
			update(1, 1, n, a[i].w);//不管是不是1都要更新啊。。 
		}   
		sort(a+1, a+n+1, cmp);
		printf("Case #%d:", ++num);
		for(int i = 1; i <= n; i++)
		{
			int t1 = min(a[i].pos1, i); 
			int t2 = a[i].pos1+a[i].add; 
		    //printf("%d %d %d\n", i, a[i].pos1, a[i].add);
			printf(" %d", t2-t1);
		}
		printf("\n");
	}
	return 0; 
} 

               这道题楼主思路想对了,就是寻找数组中的一个元素前面比它大的个数和后面比它小的个数取最大值。可是比赛的时候完全没有想到用线段树来进行查询啊。。。于是生无可恋脸的磨完了比赛~啊啊太弱了好忧桑~还是好好训练吧~o( ̄ε ̄*)


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值