牛客寒假训练营6--C

题目传送门

寒假牛客最后一场终于突破了7题,开心的一批 >_<!!!

题意比较清晰,就是问你木板最少可以分为几组,并输出每块木板被分到哪一组.

话说我的思路还是没有被列为正解 (我的思路很奇葩吗?感觉复杂度什么的也很好啊?是因为非主流吗?)

初见就锁定了这是个逆序数,二话不说写了个树状数组,但其实并不是逆序数,尽管说和逆序数很像…
首先对x进行排序,树状数组维护y就行了

在这里插入图片描述
x和y都没有重复的,所以对x排完序之后就不用管x了,然后只用考虑y就行了,y也很好考虑:

  1. 如果在已经插入的木板里不存在比当前要插入的木板的y还小的y,那就放在第一组啦.
  2. 如果已经插入的木板里只有一个比当前要插入的木板的y还小的y,那就第二组呗.
  3. 但是如果已经插入的木板里有x个比当前要插入的木板的y还小的y,那它应该放在第x+1组吗?答案是否定的.
    举例:
    4
    4 3
    3 2
    2 1
    1 4

对于这组样例最后要插入的是4,在它之前已经插入了三个比它小的数了,但是它应该被分到第二组而不是第4组…这就是逆序数不对的原因…(WA了三发才意识到…)

所以树状数组tree[k]维护的是1-k中最大被分到第几组了
当我们插入一个新的y值时 我们看一下1-y中最大的被分到第几组了然后tree[y]=max+1再向上更新就行啦!
AC代码:

#include <iostream>
#include <stack>
#include <cmath>
#include <queue>
#include <cstdio>
#include <algorithm>
#define MAX 100010
#define mod 1000000007
#define ll long long
using namespace std;

struct node{
	int x,y;
	int id;
	int ans;
}p[MAX];
int tree[MAX]={0};

int lowbit(int x)
{
	return (x&(-x));
}

int find(int x)
{
	int ans=0;
	while(x)
	{
		ans=max(tree[x],ans);
		x-=lowbit(x);
	}
	return ans;
}

void insert(int x)
{
	int num=find(x)+1;
	tree[x]=num;
	while(x<MAX)
	{
		tree[x]=max(tree[x],num);
		x+=lowbit(x);
	}
}

int cmp1(node a,node b)
{
	return a.x>b.x;
}

int cmp2(node a,node b)
{
	return a.id<b.id;
}
int main()
{
	int n;
	cin>>n;
	for(int i=0;i<n;i++)
	{
		cin>>p[i].x>>p[i].y;
		p[i].id=i;
	}
	sort(p,p+n,cmp1);
	int m=-1;
	int now=1;
	for(int i=0;i<n;i++)
	{
		insert(p[i].y);
		p[i].ans=tree[p[i].y];
		if(m<p[i].ans)
		m=p[i].ans;
	}
	sort(p,p+n,cmp2);
	cout<<m<<endl;
	for(int i=0;i<n;i++)
	cout<<p[i].ans<<" ";
	return 0;
}
/*
5
2 2
3 1
2 1
5 5
5 4
*/

贴一个官方题解:
在这里插入图片描述

这个Dilworth定理是啥… (太菜了,还要多学习…)

发布了30 篇原创文章 · 获赞 9 · 访问量 1294

猜你喜欢

转载自blog.csdn.net/Zhang_sir00/article/details/104336264