A1210. 光棱坦克
时间限制:1.0s 内存限制:512.0MB
总提交次数: AC次数: 平均分:
试题来源
2010中国国家集训队命题答辩
问题描述
一个平面直角坐标系上,有N个点,标号为1到N,其中第i个点的坐标为(x[i], y[i])。
求满足以下两个条件的点列{p[i]}的数目(假设{p[i]}的长度为M):
1) 对任意1 <= i < j <= M,必有y[p[i]] > y[p[j]];
2) 对任意3 <= i <= M,必有x[p[i-1]] < x[p[i]] < x[p[i-2]]或者x[p[i-2]] < x[p[i]] < x[p[i-1]]。
求满足条件的非空序列{p[i]}的数目,结果对一个整数Q取模。
求满足以下两个条件的点列{p[i]}的数目(假设{p[i]}的长度为M):
1) 对任意1 <= i < j <= M,必有y[p[i]] > y[p[j]];
2) 对任意3 <= i <= M,必有x[p[i-1]] < x[p[i]] < x[p[i-2]]或者x[p[i-2]] < x[p[i]] < x[p[i-1]]。
求满足条件的非空序列{p[i]}的数目,结果对一个整数Q取模。
输入格式
第1行是两个由空格隔开的整数:N和Q。
第2行到第N+1行,每行有两个整数。其中的第i行的两个整数分别是x[i]和y[i]。
第2行到第N+1行,每行有两个整数。其中的第i行的两个整数分别是x[i]和y[i]。
输出格式
输出文件只有一行,包含一个整数,表示序列{p[i]}的数目对Q取模的结果。
样例输入
4 100
2 2
3 1
1 4
4 3
2 2
3 1
1 4
4 3
样例输出
14
样例说明
一共4个点,位置如下:
如果M=4, 那么只有1种序列符合要求,如下图所示:
如果M = 3,那么有3种序列符合要求,如下图:
如果M = 2,那么有6种序列符合要求,如下图:
如果M = 1,也就是点列只包含一个点的情况。那么有4种序列。明显都符合要求。
所以一共就有1 + 3 + 6 + 4一共14种序列符合要求。
如果M=4, 那么只有1种序列符合要求,如下图所示:
如果M = 3,那么有3种序列符合要求,如下图:
如果M = 2,那么有6种序列符合要求,如下图:
如果M = 1,也就是点列只包含一个点的情况。那么有4种序列。明显都符合要求。
所以一共就有1 + 3 + 6 + 4一共14种序列符合要求。
数据规模和约定
对于25%的数据,N <= 50;对于40%的数据,N <= 700;对于60%的数据,N <= 2000;对于70%的数据,N <= 4000;对于100%的数据,1 <= N <= 7000。
对于100%的数据,有1 <= Q <= 1000000000。
对于50%的数据,保证对任何的i,x[i]和y[i]是1到N之间的整数;对于100%的数据,保证对任何的i,x[i]和y[i]都是1到2000000000之间的整数。
对于100%的数据,保证有当i != j时,有x[i] != x[j]且y[i] != y[j]。
对于100%的数据,有1 <= Q <= 1000000000。
对于50%的数据,保证对任何的i,x[i]和y[i]是1到N之间的整数;对于100%的数据,保证对任何的i,x[i]和y[i]都是1到2000000000之间的整数。
对于100%的数据,保证有当i != j时,有x[i] != x[j]且y[i] != y[j]。
/* 首先把点按照x坐标排序(不是y坐标) 设dp[i][j][0/1]代表只考虑前i个点,以第j个点为起点,下一个点在它的左边/右边的方案数. 当i增加1时,从右到左 对每个之前的点考虑第i个点造成的贡献. 当这个点在第i个点以上时,第i个点可以更新这个点的dp值; 当这个点在第i个点以下时,这个点可以更新第i个点的dp值. 显然是可以滚动数组的. 复杂度O(n*n) */ #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; struct node{ int x,y; bool operator < (const node o)const{ return x<o.x; } }pot[7010]; int n,md,dp[7010][2]; int main(){ scanf("%d%d",&n,&md); for(int i=1;i<=n;i++)scanf("%d%d",&pot[i].x,&pot[i].y); sort(pot+1,pot+n+1); for(int i=1;i<=n;i++){ dp[i][0]=dp[i][1]=1; for(int j=i-1;j>=1;j--){ if(pot[j].y<pot[i].y){ dp[i][0]+=dp[j][1]; if(dp[i][0]>=md)dp[i][0]-=md; } else{ dp[j][1]+=dp[i][0]; if(dp[j][1]>=md)dp[j][1]-=md; } } } int ans=0; for(int i=1;i<=n;i++){ ans+=dp[i][0]; if(ans>=md)ans-=md; ans+=dp[i][1]; if(ans>=md)ans-=md; } ans-=n; if(ans<0)ans+=md; printf("%d\n",ans); return 0; }