jzoj1901. Light Prism Tank

Title description

Description In
  a plane rectangular coordinate system, there are N points, labeled 1 to N, and the coordinates of the i-th point are (x[i], y[i]). Find the number of point sequences {p[i]} satisfying the following two conditions (assuming the length of {p[i]} is M): 1) For any 1 <= i <j <= M, there must be y[p [i]]> y[p[j]]; 2) For any 3 <= i <= M, there must be x[p[i-1]] <x[p[i]] <x[p[i -2]] or x[p[i-2]] <x[p[i]] <x[p[i-1]]. Find the number of non-empty sequences {p[i]} that satisfy the condition, and the result is modulo an integer Q.

Input
  line 1 is two integers separated by spaces: N and Q. From line 2 to line N+1, each line has two integers. The two integers in the i-th row are x[i] and y[i].

The Output
  output file has only one line and contains an integer, which represents the result of the modulo Q of the number of sequences {p[i]}.

Sample Input
4 100
2 2
3 1
1 4
4 3

Sample Output
14

Data Constraint

Hint
Insert picture description here
if M = 1, that is, the point column contains only one point. Then there are 4 kinds of sequences. Obviously meet the requirements. So there are a total of 14 sequences of 1 + 3 + 6 + 4 that meet the requirements. [Data Range] For 25% of the data, N <= 50; for 40% of the data, N <= 700; for 60% of the data, N <= 2000; for 70% of the data, N <= 4000; for 100 % Of the data, 1 <= N <= 7000. For 100% of the data, there is 1 <= Q <= 1000000000. For 50% of the data, ensure that for any i, x[i] and y[i] are integers between 1 and N; for 100% of the data, ensure that for any i, x[i] and y[i ] Are all integers between 1 and 2000000000. For 100% data, it is guaranteed that when i != j, x[i] != x[j] and y[i] != y[j].

70%

Let f[i][j] indicate that the currently selected point is i, and the y coordinate is j.
Obviously, it can be sorted by x from small to large + discretized y. The transfer can be recursively pushed from f[i][j] to f[ i][y[i]](j≠y[i])
If you push to a certain position, and i'>i at that position, then you can move to f[i'][j].
This time is O( n 2 ), but the constant is larger (3s ran when n=7000)

100%

Consider a more mysterious dp
to sort the points by x from small to large , let f[i] represent the right end of the sequence found as i, the next number of solutions to be found to the left, and vice versa
for each I, enumerate j from large to small , if y[j]<y[i], then f[i]+=g[j], otherwise
, the correctness of g[j]+=f[i] can be drawn. It is found that the essence of each transfer is from small to large y, so no aftereffect is still satisfied.
Note that when the length is 1, it is counted twice. The
time is still O(n 2 ), but the constant is small

code

#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#define fo(a,b,c) for (a=b; a<=c; a++)
#define fd(a,b,c) for (a=b; a>=c; a--)
#define add(a,b) a=((a)+(b))%mod
using namespace std;

struct type{
    
    
	int x,y;
} a[7001];
int f[7001];
int g[7001];
int b[7001];
int n,mod,i,j,k,l,ans;

bool cmp(type a,type b)
{
    
    
	return a.x<b.x;
}

int main()
{
    
    
//	freopen("tank14.in","r",stdin);
//	freopen("S8_13_2.in","r",stdin);
	
	scanf("%d%d",&n,&mod);
	fo(i,1,n)
	scanf("%d%d",&a[i].x,&a[i].y);
	
	sort(a+1,a+n+1,cmp);
	
	fo(i,1,n)
	{
    
    
		f[i]=1;
		
		fd(j,i-1,1)
		if (a[i].y>a[j].y)
		add(f[i],g[j]);
		else
		add(g[j],f[i]);
		
		g[i]=1;
	}
	
	fo(i,1,n)
	{
    
    
		add(ans,f[i]);
		add(ans,g[i]);
	}
	ans-=n;
	if (ans<0)
	ans+=mod;
	
	printf("%d\n",ans);
}

Guess you like

Origin blog.csdn.net/gmh77/article/details/99475996