zoukankan      html  css  js  c++  java
  • BZOJ3193 [JLOI2013]地形生成 【dp】

    题目链接

    BZOJ3193

    题解

    注意(key)是小于

    第一问,显然按高度降序排序,逐个插入
    如果高度各不相同,那么之前插入的都比当前插入的(i)大,可插入的位置个数就确定了
    由于存在高度相同的情况,将key作为第二关键字升序排序
    这样后面插入的就一定能插入前面插入的之后,统计一下之前插入了(cnt)个相同高度的,可插入的位置就加上(cnt)

    第二问
    如果高度各不相同,答案同第一问
    否则要考虑相同高度带来的影响
    分段(dp)计算每一段相同高度的贡献

    我们默认(key)大的放在(key)小的后面
    (f[i][j])为该段第(i)个插入位置(j)的方案数
    首先(j)要在可插入范围内
    然后就是

    [f[i][j] = sumlimits_{k = 1}^{j - 1}f[i - 1][k] ]

    前缀和优化一下就是(O(n^2))

    #include<algorithm>
    #include<iostream>
    #include<cstdlib>
    #include<cstring>
    #include<cstdio>
    #include<vector>
    #include<queue>
    #include<cmath>
    #include<map>
    #define LL long long int
    #define REP(i,n) for (int i = 1; i <= (n); i++)
    #define Redge(u) for (int k = h[u],to; k; k = ed[k].nxt)
    #define cls(s,v) memset(s,v,sizeof(s))
    #define mp(a,b) make_pair<int,int>(a,b)
    #define cp pair<int,int>
    using namespace std;
    const int maxn = 1005,maxm = 100005,INF = 0x3f3f3f3f,P = 2011;
    inline int read(){
    	int out = 0,flag = 1; char c = getchar();
    	while (c < 48 || c > 57){if (c == '-') flag = 0; c = getchar();}
    	while (c >= 48 && c <= 57){out = (out << 1) + (out << 3) + c - 48; c = getchar();}
    	return flag ? out : -out;
    }
    struct node{int h,key;}e[maxn];
    inline bool operator <(const node& a,const node& b){
    	return a.h == b.h ? a.key < b.key : a.h > b.h;
    }
    int n,f[maxn][maxn],sum[maxn];
    void work1(){
    	int ans = 1,cnt = 0;
    	for (int i = 1; i <= n; i++,cnt++){
    		if (i == 1 || e[i].h != e[i - 1].h) cnt = 0;
    		ans = ans * (min(e[i].key,i - 1 - cnt) + 1 + cnt) % P;
    	}
    	printf("%d ",ans);
    }
    void work2(){
    	int ans = 1;
    	for (int i = 1,nxt; i <= n; i = nxt + 1){
    		nxt = i;
    		while (nxt < n && e[nxt + 1].h == e[i].h) nxt++;
    		int E = min(e[i].key,i - 1) + 1;
    		for (int j = 1; j <= E; j++) f[i][j] = 1;
    		for (int j = 1; j <= n; j++) sum[j] = (sum[j - 1] + f[i][j]) % P;
    		for (int u = i + 1; u <= nxt; u++){
    			int cnt = u - i,E = min(e[u].key,u - 1 - cnt) + 1 + cnt;
    			for (int j = 1; j <= E; j++){
    				f[u][j] = 0;
    				f[u][j] = (f[u][j] + sum[j - 1]) % P;
    			}
    			for (int j = 1; j <= n; j++)
    				sum[j] = (sum[j - 1] + f[u][j]) % P;
    		}
    		int tot = 0; E = min(e[nxt].key,nxt - 1 - nxt + i) + 1 + nxt - i;
    		for (int j = 1; j <= E; j++) tot = (tot + f[nxt][j]) % P;
    		//printf("mult %d
    ",tot);
    		ans = ans * tot % P;
    	}
    	printf("%d
    ",ans);
    }
    int main(){
    	n = read();
    	REP(i,n) e[i].h = read(),e[i].key = read() - 1;
    	sort(e + 1,e + 1 + n);
    	work1();
    	work2();
    	return 0;
    }
    
    
  • 相关阅读:
    Python 递归
    Python 面向过程编程
    Python 协程函数
    Python-第三方库requests详解
    Python 三元表达式
    linux copy
    centos 安装软件
    mysql 权限
    mysql 权限 备份
    android 开发
  • 原文地址:https://www.cnblogs.com/Mychael/p/9287624.html
Copyright © 2011-2022 走看看