首页 > 其他分享 >hdu 3564(线段树+LIS)

hdu 3564(线段树+LIS)

时间:2023-05-29 22:36:57浏览次数:57  
标签:hdu 3564 int 线段 mid 插入 LIS include


题意:给出1~n的插入顺序,要求每次插入之后的LIS


解题思路:这道题确实挺难想的,我最开始想用树状数组每插入一个数就更新一次,如果这么想,那么你就输了。它这里的想法是先将1-n的最终位置都保存起来,然后再一个个去找LIS。这里有点离线算法的意思,至少了解到更新时可以先别急着处理。还有这里要总结一种线段树的用法,就是在空格处去填充数字,确实结合了这道题的特点把线段树用的很灵活。。。






#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;

const int maxn = 100005;
struct Segment
{
	int l,r;
	int cnt; //cnt记录空位的数量
}tree[maxn<<2];
int n,len,pos[maxn],ans[maxn],dp[maxn];

void build(int rt,int l,int r)
{
	tree[rt].l = l, tree[rt].r = r;
	tree[rt].cnt = 1;
	if(l == r) return;
	int mid = (l + r) >> 1;
	build(rt<<1,l,mid);
	build(rt<<1|1,mid+1,r);
	tree[rt].cnt = tree[rt<<1].cnt + tree[rt<<1|1].cnt;
}

void insert(int rt,int x,int m)	//表示m要插入x的位置
{
	if(tree[rt].l == tree[rt].r)
	{
		ans[m] = tree[rt].l;
		tree[rt].cnt = 0;
		return;
	}
	tree[rt].cnt--;	//要插入一个数,表示这段区间内有一个空会被占
	if(x <= tree[rt<<1].cnt)
		insert(rt<<1,x,m);
	else insert(rt<<1|1,x-tree[rt<<1].cnt,m);
}

int binsearch(int val)
{
	int l = 1, r = len, mid;
	while(l <= r)
	{
		mid = (l + r) >> 1;
		if(val > dp[mid])
			l = mid + 1;
		else r = mid - 1;
	}
	return l;
}

int main()
{
	int t,cas = 1;
	scanf("%d",&t);
	while(t--)
	{
		scanf("%d",&n);
		for(int i = 1; i <= n; i++)
		{
			scanf("%d",&pos[i]);
			pos[i]++;
			dp[i] = 0;
		}
		build(1,1,n);
		for(int i = n; i >= 1; i--)	//必须要逆着遍历,因为最后一个加入的数是可以确定位置的,倒数第二个数在最后一个数确定的情况下再找位置,以此类推
			insert(1,pos[i],i);		//也就是说,越往后加入进来的数,它选择位置的权利更大,这是种逆向思维
		printf("Case #%d:\n",cas++);
		len = 0;
		for(int i = 1; i <= n; i++)
		{
			int k = binsearch(ans[i]);
			len = max(len,k);
			dp[k] = ans[i];
			printf("%d\n",len);
		}
		printf("\n");
	}
	return 0;
}




标签:hdu,3564,int,线段,mid,插入,LIS,include
From: https://blog.51cto.com/u_16143128/6374309

相关文章

  • hdu 3874(树状数组+离线算法)
    解题思路:这道题和之前的题一样,查找[l,r]区间内不重复数字的和。可以利用离线算法,实际上离线算法为了解决在查找时出现的矛盾,因为每次询问的区间大小不同,如果单独处理的话可能会对之后的查询有影响,所以离线算法帮助我们把要查询的区间先按照右端点进行排序,因为在处理更靠右的区间时,......
  • hdu 4101(bfs+博弈)
    题意:题目的意思就是说两个人轮流玩游戏,给你一张地图,这个地图中间有一点-1代表宝藏,AliandBaba轮流走路,如果某一个人能够直接走到宝藏的话,那么他就赢了。地图上其它的点0代表空地,数字代表当前地点的石子当某一人拿石子的时候,他只能拿走一颗。问你谁最后能拿到宝藏;解题思路:宝藏位于-......
  • Java8 List集合如何移除满足条件的元素
    1.移除List<String>中指定元素for(inti=assSupplementList.size()-1;i>=0;i--){TypgHouseOrderAssessmentSupplementitem=assSupplementList.get(i);if(item.getBzx().contains("新建房屋")){ass......
  • java集合过滤出符合条件的List元素集合(lambda表达式)
    使用Java8中的lambda表达式过滤ModelMapmodel=newModelMap();TSmClazzTSmClazz=tSmClazzService.get(id);List<Student>students=TSmClazz.getStudents();if(flag.equals("0")){List<Student>boys......
  • hdu 1510
    WhiteRectanglesTimeLimit:2000/1000MS(Java/Others)    MemoryLimit:65536/32768K(Java/Others)ProblemDescriptionYouaregivenachessboardmadeupofNsquaresbyNsquareswithequalsize.Someofthesquaresarecoloredblack,andthe......
  • hdu 2821
    题意:n*m的格子上有一些方块放在某些格子上,一个格子可能有几个方块,用'a'-'z'来表示方块数量。初始的时候可以选择任意空地作为Pusher初始点,Pusher选择一个方向,然后向这个方向前进直到遇到有方块的格子,Pusher把这个格子的方块清除一个,并把它向前推一格(向前不能出界),如果前面一格有方......
  • hdu 1534(差分约束)
    题意:安排计划,有4种约束方式,给出你这些时间的n个约束..如果计划是可行的,求出每一件事发生的最早时间..否则输出“impossible”..①.FAFaba要在b完成后完成..②.FASaba要在b开始前完成..③.SASaba要在b开始前开始..④.SAFaba要在b结束前开......
  • hdu 1532(最大流)
    解题思路:这是一道典型的模板题,直接套用EK算法即可。。。我感觉最大流的本质就是能否找到一个从源点到汇点的增广路径,并将其最小的边作为增加值,沿着增广路上的边进行更新。AC:#include<iostream>#include<cstdio>#include<cstring>#include<queue>usingnamespacestd;consti......
  • hdu 5074(简单dp)
    HatsuneMikuTimeLimit:2000/1000MS(Java/Others)    MemoryLimit:262144/262144K(Java/Others)ProblemDescriptionHatsuneMikuisapopularvirtualsinger.ItisverypopularinbothJapanandChina.Basicallyitisacomputersoftwarethata......
  • hdu 3303(线段树+抽屉原理)
    解题思路:这题利用了抽屉原理,即1-M之间的所有数与M+1的模都不相同。那么可以利用它将要查找所有区间分成[1,Y-1],[Y,2*Y-1],[2*Y,3*Y-1].........一直下去,直到所有的区间都被找一遍,然后就是保存最小的模即可。。。这样就肯定要找每个区间的最小的模,实际上这里可以利用线段树去找,只需......