UVA12141 Line Chart 题解
题目翻译
小 F 打过
若一场比赛在折线图上的对应点
小 F 认为一个有
注意:我们认为两种折线图是不同的,当且仅当两张图上各个点的纵坐标依次排列形成的序列不同。
分析
计数问题考虑 dp。首先显然我们可以按
比较显然的是,我们可以设
转移比较显然。
需要注意的是,由于题目中对折线图不同的定义没有考虑点的横坐标,我们发现对于两个点
直接转移的复杂度是
注意当
优化后时间复杂度为
Code
#include<bits/stdc++.h>
#define rep(i,j,k) for(int i=j;i<=k;i++)
#define repp(i,j,k) for(int i=j;i>=k;i--)
#define ls(x) x*2
#define rs(x) x*2+1
#define mp make_pair
#define fir first
#define sec second
#define pii pair<int,int>
#define lowbit(x) x&-x
#define ctl(x) floor(log2(x))
#define ppc(x) __builtin_popcount(x)
#define qingbai666 qwq
using namespace std;
typedef long long ll;
const int N=10055,M=55,mo=1000000,inf=1e9+7;
void read(int &p){
int x=0,w=1;
char ch=0;
while(!isdigit(ch)){
if(ch=='-')w=-1;
ch=getchar();
}
while(isdigit(ch)){
x=(x<<1)+(x<<3)+ch-'0';
ch=getchar();
}
p=x*w;
}
int cases;
int n,m,cntv;
pii a[N];
struct BIT{
int t[N],val[N];//权值BIT,下标离散化.
void add(int x,int v){
v=(v%mo+mo)%mo;
for(int i=x;i<=cntv;i+=lowbit(i))
t[i]+=v,t[i]%=mo;
}
void modify(int x,int v){
add(x,v-val[x]);
val[x]=v;
}
int query(int x){
int ret=0;
for(int i=x;i;i-=lowbit(i))
ret+=t[i],ret%=mo;
return ret;
}
}T[M][3];
int dp[N][M][3],v[N];
void solve(int tms){
read(n),read(m);
rep(i,0,n){
rep(j,0,m){
rep(k,0,2)
dp[i][j][k]=T[j][k].t[i]=T[j][k].val[i]=0;
}
}
cntv=0;
rep(i,1,n)
read(a[i].fir),read(a[i].sec),v[++cntv]=a[i].sec;
sort(a+1,a+n+1),sort(v+1,v+cntv+1),cntv=unique(v+1,v+cntv+1)-v-1;
rep(i,1,n)
a[i].sec=lower_bound(v+1,v+cntv+1,a[i].sec)-v;
int ans=0;
rep(i,1,n){
rep(j,0,m){
if(j==0)dp[i][j][2]=1;
dp[i][j][0]+=(j>=1?(T[j-1][1].query(cntv)-T[j-1][1].query(a[i].sec)):0);
dp[i][j][0]+=(T[j][2].query(cntv)-T[j][2].query(a[i].sec))+(T[j][0].query(cntv)-T[j][0].query(a[i].sec));
dp[i][j][1]+=T[j][1].query(a[i].sec-1)+T[j][2].query(a[i].sec-1);
dp[i][j][1]+=(j>=1?T[j-1][0].query(a[i].sec-1):0);
dp[i][j][0]=(dp[i][j][0]%mo+mo)%mo,dp[i][j][1]=(dp[i][j][1]%mo+mo)%mo;
rep(k,0,2)
T[j][k].modify(a[i].sec,dp[i][j][k]);
}
}
rep(k,0,2)
ans+=T[m][k].query(cntv);
if(m==0)ans++;//删完,一个不剩
printf("Case %d: %d\n",tms,ans%mo);
}
int main(){
read(cases);
rep(i,1,cases)
solve(i);
return 0;
}