【树状数组】【dp】折线统计

【描述】
二维平面上有n个点(xi, yi),现在这些点中取若干点构成一个集合S,对它们按照x坐标排序,顺次连接,将会构成一些连续上升、下降的折线,设其数量为f(S)。如下图中,1->2,2->3,3->5,5->6(数字为下图中从左到右的点编号),将折线分为了4部分,每部分连续上升、下降。
在这里插入图片描述
现给定k,求满足f(S) = k的S集合个数。( n < = 50000 , k < = 10 , x i , y i < = 1 e 5 n<=50000,k<=10,x_i,y_i<=1e5 )
【思路】
这题其实挺简单的。首先对点按x排序,从左往右考虑转移。考虑转移时我们需要什么:1.点的位置 2.当前形成的折线方向 3.当前构成的折线段数。所以定义f[i][j][0/1]表示以第i个点结尾,已经构成了j段折线,折线方向向上/向下。转移很显然:
f [ i ] [ j ] [ 0 ] = k < i y [ k ] < y [ i ] f [ k ] [ j ] [ 0 ] + k < i y [ k ] < y [ i ] f [ k ] [ j 1 ] [ 1 ] f[i][j][0]=\sum_{k<i且y[k]<y[i]} f[k][j][0]+\sum_{k<i且y[k]<y[i]}f[k][j-1][1]
f [ i ] [ j ] [ 1 ] = k < i y [ k ] > y [ i ] f [ k ] [ j ] [ 1 ] + k < i y [ k ] > y [ i ] f [ k ] [ j 1 ] [ 0 ] f[i][j][1]=\sum_{k<i且y[k]>y[i]} f[k][j][1]+\sum_{k<i且y[k]>y[i]}f[k][j-1][0]
考虑前缀和优化,但是y[k]<y[i]的限制很讨厌。注意到点的坐标很小,我们可以用树状数组来优化转移。
代码:

#include<bits/stdc++.h>
#define re register
#define mp make_pair
using namespace std;
const int N=1e5+5,mod=1e5+7;
inline int red(){
    int data=0;bool w=0; char ch=getchar();
    while(ch!='-' && (ch<'0' || ch>'9')) ch=getchar();
    if(ch=='-') w=1,ch=getchar();
    while(ch>='0' && ch<='9') data=(data<<3)+(data<<1)+ch-'0',ch=getchar();
    return w?-data:data;
}int n,m,mx;
struct point{
	int x,y;
	friend inline bool operator<(const point&a,const point&b){return a.x<b.x;}
}p[N];
inline int add(const int&a,const int&b){return a+b>=mod?a+b-mod:a+b;}
inline int dec(const int&a,const int&b){return a<b?a-b+mod:a-b;}
inline void Add(int&a,const int&b){((a+=b)>=mod)&&(a-=mod);}
struct tree{
	int c[N];
	inline void add(int x,const int&v){while(x<=mx)Add(c[x],v),x+=x&(-x);}
	inline int query(int x){int ret=0;
		while(x)Add(ret,c[x]),x-=x&(-x);return ret;
	}
}bit[11][2];
int main(){n=red();m=red();
	for(int re i=1;i<=n;i++)p[i]=(point){red(),red()},mx=max(mx,p[i].y);
	sort(p+1,p+n+1);
	for(int re i=1;i<=n;i++){
		bit[0][0].add(p[i].y,1);
		bit[0][1].add(p[i].y,1);
		for(int re k=1;k<=m;k++){
			bit[k][0].add(p[i].y,add(bit[k][0].query(p[i].y-1),bit[k-1][1].query(p[i].y-1)));
			bit[k][1].add(p[i].y,add(dec(bit[k][1].query(mx),bit[k][1].query(p[i].y)),dec(bit[k-1][0].query(mx),bit[k-1][0].query(p[i].y))));
		}
	}cout<<add(bit[m][0].query(mx),bit[m][1].query(mx))<<"\n";
}
发布了106 篇原创文章 · 获赞 22 · 访问量 5506

猜你喜欢

转载自blog.csdn.net/weixin_44111457/article/details/101643737