zoukankan      html  css  js  c++  java
  • ARC065 简要题解

    ARC065 简要题解

    A

    从前往后不好做, 那就直接从后往前

    B

    考虑设 (f[i][j]) 为在第一张图中属于 (i) 集合, 在第二张图中属于 (j) 集合的点的个数
    这样会 MLE , 但是又发现有用的 ((i, j)) 不会很多, 直接 (map) 存下来就行了

    C

    转化为切比雪夫距离之后直接从起点 bfs , 把横纵坐标离散化之后存在 set 中, 找到一个就删掉他, 这样就可以保证 bfs 的复杂度是对的了
    然后对于每个点算一次贡献
    发现一个点对会算两次, 最后把答案除以二就行了

    D

    互相包含的区间是没有用的, 证明的话考虑把小的那个区间挖出去
    然后就可以把所有的区间变成左端点和右端点都单调递增的区间了
    那么一个区间控制的范围就是他的左端点到 min(他的右端点, 下一个区间的左端点 - 1)
    (f[i][j]) 为前 (i) 个点控制的范围中放置了 (j) 个 1 并且合法的方案
    枚举一个 (k) 然后从 (f[i - 1][j - k]) 转移过来, 乘个组合数就行了
    复杂度 (O(n^3)) , 但根据网上题解的说法, 复杂度是 (O(n ^ 2))
    有点没讲清楚细节, 放下代码吧

    Code

    #include <algorithm>
    #include <iostream>
    #include <cstring>
    #include <cstdio>
    const int N = 3e3 + 5;
    const int mod = 1e9 + 7; 
    using namespace std;
    
    int n, m, a[N], l[N], r[N], vis[N], sum[N], c[N][N], f[N][N], mx[N], len[N]; 
    struct node
    {
    	int l, r;
    	bool operator < (const node &p) const
    		{
    			return l == p.l ? r > p.r : l < p.l; 
    		}
    } p[N];
    char s[N]; 
    
    template < typename T >
    inline T read()
    {
    	T x = 0, w = 1; char c = getchar();
    	while(c < '0' || c > '9') { if(c == '-') w = -1; c = getchar(); }
    	while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
    	return x * w; 
    }
    
    int main()
    {
    #ifndef ONLINE_JUDGE
    	freopen("cpp.in", "r", stdin); 
    #endif
    	n = read <int> (), m = read <int> (), scanf("%s", s + 1);
    	for(int i = 1; i <= n; i++) a[i] = s[i] - '0';
    	for(int i = 1; i <= m; i++) p[i].l = read <int> (), p[i].r = read <int> ();
    	for(int i = 1; i <= m; i++)
    		for(int j = p[i].l; j <= p[i].r; j++) vis[j] = 1; 
    	sort(p + 1, p + m + 1); int tmp = m; m = 0;
    	for(int x = 0, i = 1; i <= tmp; i++)
    		if(p[i].r > x) x = p[i].r, p[++m] = p[i]; 
    	p[m + 1].l = n * 2; 
    	for(int i = 1; i <= n; i++) sum[i] = sum[i - 1] + vis[i] * a[i]; 
    	for(int i = 1; i <= m; i++) mx[i] = sum[p[i].r]; 
    	for(int i = 1; i <= m; i++) l[i] = p[i].l, r[i] = min(p[i + 1].l - 1, p[i].r), len[i] = len[i - 1] + r[i] - l[i] + 1; 
    	for(int i = 0; i <= n; i++)
    		for(int j = 0; j <= i; j++)
    			c[i][j] = (!j ? 1 : (c[i - 1][j - 1] + c[i - 1][j]) % mod); 
    	f[0][0] = 1; 
    	for(int i = 1; i <= m; i++)
    		for(int j = 0; j <= mx[i - 1]; j++)
    			for(int k = 0; k <= mx[i] - j; k++)
    			{
    				if((mx[i] - j - k) > p[i].r - r[i] || (p[i].r - r[i] + j + k - mx[i]) > p[i].r - r[i]) continue; 
    				f[i][j + k] = (1ll * c[r[i] - l[i] + 1][k] * f[i - 1][j] + f[i][j + k]) % mod;
    			}
    	printf("%d
    ", f[m][sum[n]]); 
    	return 0; 
    }
    
  • 相关阅读:
    acm常见错误-持续更新
    学习之旅
    快速幂
    写个管理自我的小工具
    Tree构建
    Sql server学习
    asp.net webAPI学习
    AngularJS数据双向绑定
    虚拟机学习
    wps学习
  • 原文地址:https://www.cnblogs.com/ztlztl/p/13619871.html
Copyright © 2011-2022 走看看