[Ybt gold medal navigation 1-2-3] Broken line statistics

Broken line statistics

Topic link: ybt gold medal navigation 1-2-3

Topic

There are some points on a graph, so that the horizontal and vertical coordinates of any two points are not the same.
If you select some sets and connect them in sequence according to the x-coordinate order, some continuous rising and falling polylines will be formed, and you will be asked how many sets are satisfied if the number of polylines is k.
The quantity is modulo 100007.

Ideas

For this question, let’s consider how to do it with ordinary dp.

Because press xxThe x- coordinates are connected side by side, then we first pressxxThe x coordinates are sorted from smallest to largest. Then if you choose a set here, the ones that are connected here must be connected.

Then we set fi, j, k f_{i,j,k}fi,j,k为前iii points must be selectediiSelected from point i to formjjj segment, and the state of the last segment iskkk。( k k k only rises0 00 and down1 11 Two values)
It is easy to think that the transfer equation is divided into rising and falling first, and then it is either the same or different from the original last stage.

We first become ascending, that is, k = 0 k=0 after the transferk=0 situation.
If it does not change, then the number of segments does not change, and the first dimension must enumerate1 11 arrivali - 1 i-1i1 k k k or0 00 .
If it changes, then the number of segments will increase, and the original will be− 1 -11 , the first dimension is still the enumeration1 ∼ i − 1 1\sim i-11i1 , the originalkkk becomes1 11

That becomes a decline, which is the same reason.
But the first dimension is not the enumeration 1 ∼ i − 1 1\sim i-11i1 , buti + 1 ∼ 100000 i+1\sim 100000i+11 0 0 0 0 0 because you change from high to low.

As for initialization, it is fi, 0, 0 = fi, 0, 1 = 1 f_{i,0,0}=f_{i,0,1}=1fi,0,0=fi,0,1=1

But your enumeration will time out.
Then we consider optimizing it with some data structures.
This requires interval sums and single-point update values. It is easy to think of using tree arrays.
Then enumerate 1 ∼ i − 1 1\sim i-11i1 is to directly queryi − 1 i-1iThe position of 1 ,i + 1 ∼ 100000 i+1\sim 100000i+11 0 0 0 0 0 , just use query100000 1000001 0 0 0 0 0 minus the queryiiThe resulting value of i . (The idea of ​​prefix sum)

Then basically it's fine, remember to take the modulo.

Code

#include<cstdio>
#include<algorithm>
#define mo 100007
#define ll long long

using namespace std;

struct node {
    
    
	int x, y;
}zb[100001];
int n, k;
ll f[50001][11][2], tree[100001][11][2], re, ans;

bool cmp(node X, node Y) {
    
    
	return X.x < Y.x;
}

void add(int now, int j, int k, ll add_num) {
    
    //树状数组操作
	for (int i = now; i <= 100000; i += i & (-i))
		tree[i][j][k] = (tree[i][j][k] + add_num) % mo;
}

ll get(int now, int j, int k) {
    
    
	re = 0;
	for (int i = now; i; i -= i & (-i))
		re = (re + tree[i][j][k]) % mo;
	return re;
}

int main() {
    
    
	scanf("%d %d", &n, &k);
	
	for (int i = 1; i <= n; i++) {
    
    
		scanf("%d %d", &zb[i].x, &zb[i].y);
	}
	
	sort(zb + 1, zb + n + 1, cmp);//按 x 坐标排序
	
	f[0][0][0] = 1;
	f[0][0][1] = 1;
	for (int i = 1; i <= n; i++) {
    
    
		f[i][0][0] = 1;
		f[i][0][1] = 1;
		
		add(zb[i].y, 0, 0, 1);
		add(zb[i].y, 0, 1, 1);//初始化
		
		for (int j = 1; j <= k; j++) {
    
    
			f[i][j][0] = (get(zb[i].y - 1, j, 0) + get(zb[i].y - 1, j - 1, 1)) % mo;
			//可以是跟前面一样上升,也可以变换,成为新的一段
			f[i][j][1] = ((get(100000, j, 1) - get(zb[i].y, j, 1) + get(100000, j - 1, 0) - get(zb[i].y, j - 1, 0)) % mo + mo) % mo;
			//同理,可以跟前面一样下降,也可以变换,由原来的上升变成下降
			//不过因为你是要下降,那你就要用全部减去上升的,才可以得到下降的
			//树状数组搞的是上升的,那如果你找 100000,就是最大值的话,就所有都找了一遍,就是全部的了
			//或者说这就是前缀和的思想
			
			add(zb[i].y, j, 0, f[i][j][0]);
			add(zb[i].y, j, 1, f[i][j][1]);
			//放进树状数组里面
		}
		
		ans = (ans + f[i][k][0]) % mo;//统计答案
		ans = (ans + f[i][k][1]) % mo;
	}
	
	printf("%lld", ans);
	
	return 0;
}

Guess you like

Origin blog.csdn.net/weixin_43346722/article/details/113107512