[JLOI2013]地形生成
3193
首先按照第一关键字高度倒叙,第二关键字顺序的顺序排序
第一问O(n) dp一下
考虑一下第i个山能放在哪些山的后面,对于比第i个山高的,只能放在前关键字个的后面,但排在他的前面的和他一样高的的后面都可以放,因为他的关键字比已放的大
第二问大概就不能O(n)了...
我们强制让一样高的关键字从小到大排列。如果\(d[i]\)表示当前一个放在第 i个比他们高的后面,可以从\(i\in[0,i-1]\)转移过来
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
const int P = 2011;
const int M = 1101;
int res=1,n,m,k,sum,f[M],d[M];
struct vv
{
int x,y;
}a[M];
bool cmp(vv a,vv b) { return a.x!=b.x ? a.x>b.x: a.y<b.y; }
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d%d",&a[i].x,&a[i].y);
sort(a+1,a+1+n,cmp);
for(int i=1;i<=n;i++)
{
if(a[i].x!=a[i-1].x)
{
sum+=k;
k=0;
}
res=res*(min(a[i].y,sum+1)+k)%P;
k++;
}
printf("%d ",res);
sum=0; res=1;
for(int i=1;i<=n;)
{
int z=i;
while(a[i].x==a[z].x) z++;
memset(d,0,sizeof(d));
d[0]=1;
for(int j=i;j<z;j++)
{
f[0]=1;
for(int l=1;l<=sum;l++) f[l]=(f[l-1]+d[l])%P;
for(int l=1;l<a[j].y;l++) d[l]=(d[l]+f[l-1])%P;
}
int k=0;
for(int j=0;j<=sum;j++) k+=d[j];
k%=P; sum+=z-i; i=z;
res=res*k%P;
}
printf("%d",res);
}