zoukankan      html  css  js  c++  java
  • 神仙题1.0

    灭虫

    题目链接
    【问题描述】
    你需要在一条无限长的道路上喷洒杀虫剂。
    在这条道路上,总共有 N 个投放点,其中第 i 个投放点在数轴上坐标 pi 处。在每一
    个投放点,你可以选择往左喷洒或往右喷洒。但是由于风向和地理环境的影响,向左喷洒和
    向右喷洒的效果不一定相同。具体来说,在一个位置向左喷洒,可以覆盖 [pi - li, pi] 这一段
    区域,而向右喷洒可以覆盖 [pi, pi + ri] 这一段区域。
    请你决定每个投放点是向左喷洒还是向右喷洒,来使得被杀虫剂覆盖的路段长度和最大。
    【输入】
    第一行 N。
    接下来 N 行,每行 pi, li, ri。
    【输出】
    输出最大的被杀虫剂覆盖的长度和。

    Input Output
    4
    1 2 2
    3 3 3
    4 3 3
    6 2 2
    Output
    9

    样例说明
    让第一个和第三个投放点向左喷洒,其他投放点向右喷洒。
    这样能覆盖的区域是 [-1,8],总长度为 9。
    【数据说明】
    对于测试点 1、 2, N≤ 15;
    对于测试点 3、 4, N≤ 3,000, ri = 0;
    对于测试点 5、 6, N≤ 30;
    对于测试点 7、 8, N≤ 300;
    对于测试点 9、 10, N≤ 3,000;
    保证 pi, li, ri ≤ 10^9。
    Code

    #include<bits/stdc++.h>
    using namespace std;
    const int N = 3010, inf = 1e9 + 7;
    int n;
    struct node {
    	int p, l, r;
    	bool operator < (const node &z) const {
    		return p < z.p;
    	}
    } a[N];
    int b[N * 3], tot, f[N][N * 3], id[N * 3];
    int main() {
    	//freopen("kill.in", "r", stdin);
    	//freopen("kill.out", "w", stdout);
    	scanf("%d", &n);
    	for (int i = 1; i <= n; i++) {
    		scanf("%d%d%d", &a[i].p, &a[i].l, &a[i].r);
    		a[i].l = a[i].p - a[i].l; a[i].r = a[i].p + a[i].r;
    		b[++tot] = a[i].p; b[++tot] = a[i].l; b[++tot] = a[i].r;
    	}
    	sort(b + 1, b + 1 + tot); tot = unique(b + 1, b + 1 + tot) - b - 1;
    	sort(a + 1, a + 1 + n);
    	for (int i = 1; i <= n; i++) {
    		a[i].p = lower_bound(b + 1, b + 1 + tot, a[i].p) - b;
    		a[i].l = lower_bound(b + 1, b + 1 + tot, a[i].l) - b;
    		a[i].r = lower_bound(b + 1, b + 1 + tot, a[i].r) - b;
    		id[a[i].p] = i;
    	}
        //f[i][j]表示前i个区间,贡献最右点小于等于j
    	for (int i = 1; i <= n; i++) {
    		for (int j = 1; j <= tot; j++) f[i][j] = f[i - 1][j];
    		for (int j = a[i].l + 1; j <= a[i].p; j++) 
                f[i][j] = max(f[i][j], f[i][j - 1] + b[j] - b[j - 1]);
            //i区间贡献(k,j]
    		int mx = f[i - 1][a[i].p];
    		for (int j = a[i].p + 1; j <= a[i].r; j++) {
    			f[i][j] = max(f[i][j], mx + b[j] - b[a[i].p]);
                //i区间贡献(a[i].p,j]
    			if (id[j] && a[id[j]].l < a[i].p) mx = max(mx, f[i - 1][a[id[j]].l] + b[a[i].p] - b[a[id[j]].l]);
    		    //相交
            }
    		for (int j = 2; j <= tot; j++) f[i][j] = max(f[i][j], f[i][j - 1]);
    	}
    	printf("%d
    ", f[n][tot]);
    	return 0;
    } 
    

    「ARC098F」Donation

    题目链接
    题目描述

    给定一张 (n) 个点,(m) 条边的无向图。这张图的每个点有两个权值 (a_i,b_i)​。你将会从这张图中选出一个点作为起点,随后开始遍历这张图。你能到达一个节点 (i) 当且仅当你的手上有至少 (a_i)​ 元钱。当你到达一个节点 (i) 后,你可以选择对这个点捐赠 (b_i)​ 元。你需要对每个点捐赠一次。问你身上至少要带多少元钱?
    Code

    #include<bits/stdc++.h>
    
    #define int long long
    #define RG register
    
    using namespace std;
    template<class T> inline void read(T &x) {
    	x = 0; RG char c = getchar(); bool f = 0;
    	while (c != '-' && (c < '0' || c > '9')) c = getchar(); if (c == '-') c = getchar(), f = 1;
    	while (c >= '0' && c <= '9') x = x*10+c-48, c = getchar();
    	x = f ? -x : x;
    	return ;
    }
    template<class T> inline void write(T x) {
    	if (!x) {putchar(48);return ;}
    	if (x < 0) x = -x, putchar('-');
    	int len = -1, z[20]; while (x > 0) z[++len] = x%10, x /= 10;
    	for (RG int i = len; i >= 0; i--) putchar(z[i]+48);return ;
    }
    const int N = 1e5 + 10;
    vector<int> e[N];
    int n, m, a[N], b[N], p[N], f[N], fa[N], Sum[N];
    bool vis[N];
    int find(int x) { return fa[x] == x ? x : fa[x] = find(fa[x]); }
    bool cmp(int x, int y) { return a[x] < a[y]; }
     main() {
    	//freopen(".in", "r", stdin);
    	//freopen(".out", "w", stdout);
    	read(n), read(m);
    	for (int i = 1; i <= n; i++) {
    		read(a[i]), read(b[i]);
    		a[i] = max(a[i] - b[i], 0ll);
    		p[i] = i, fa[i] = i;
    	}
    	for (int i = 1, x, y; i <= m; i++) {
    		read(x), read(y);
    		e[x].push_back(y); e[y].push_back(x);
    	}
    	sort(p + 1, p + 1 + n, cmp);
    	for (int i = 1; i <= n; i++) {
    		int u = p[i]; vis[u] = 1;
    		Sum[u] = b[u];
    		vector<int> son;
    		for (auto v : e[u]) {
    			if (!vis[v] || find(v) == u) continue;
    			Sum[u] += Sum[find(v)];
    			son.push_back(find(v));
    			fa[find(v)] = u;
    		}
    		f[u] = Sum[u] + a[u];
    		for (auto v : son) f[u] = min(f[u], max(a[u], f[v]) + Sum[u] - Sum[v]); 
    	}
    	printf("%lld
    ", f[p[n]]);
    	return 0;
    }
    
    

    AT2294 Eternal Average

    【题目链接】
    luogu
    atcoder

    题目描述
    黑板上有(n)个0和(m)个1,我们每次选择(k)个数字将其擦除,然后把它们的平均数写上去,这样一直操作直到只剩下一个数字,问剩下的这个数字有多少种不同的情况。

    答案对(10^9+7)取模

    (1 leq n,m leq 2000,2 leq k leq 2000)

    保证(n+m-1)能被(k)整除。

    Code

    #include<bits/stdc++.h>
    
    #define LL long long
    #define RG register
    
    using namespace std;
    template<class T> T gi() {
    	T x = 0; bool f = 0; char c = getchar();
    	while (c != '-' && (c < '0' || c > '9')) c = getchar();
    	if (c == '-') f = 1, c = getchar();
    	while (c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
    	return f ? -x : x;
    }
    const int N = 2010, Mod = 1e9 + 7;
    int f[N << 1][N][2], n, m, k, ans, sum[N];
    int main() {
    	//freopen(".in", "r", stdin);
    	//freopen(".out", "w", stdout);
    	f[0][0][0] = 1;
    	n = gi<int>(), m = gi<int>(), k = gi<int>();
    	for (int i = 1; i <= n + m; i++) {
    		for (int j = 0; j <= m; j++) {
    			f[i][j][0] = (f[i - 1][j][0] + f[i - 1][j][1]) % Mod;
    			sum[j] = ((j ? sum[j - 1] : 0) + f[i][j][0]) % Mod;
    			if (j) f[i][j][1] = (sum[j - 1] - (j - k < 0 ? 0 : sum[j - k]) + Mod) % Mod;
    		}
    		for (int j = 0; j <= m; j++)
    			if (j % (k - 1) == m % (k - 1) && (k - 1) * i - j + 1 <= n &&
    				((k - 1) * i - j + 1) % (k - 1) == n % (k - 1))
    				ans = (ans + f[i][j][1]) % Mod;
    	}
    	printf("%d
    ", ans);
    	return 0;
    }
    
    

    【BZOJ3711】Druzyny

    题目链接

    Description
    体育课上,n个小朋友排成一行(从1到n编号),老师想把他们分成若干组,每一组都包含编号连续的一段小朋友,每个小朋友属于且仅属于一个组。
    第i个小朋友希望它所在的组的人数不多于d[i],不少于c[i],否则他就会不满意。
    在所有小朋友都满意的前提下,求可以分成的组的数目的最大值,以及有多少种分组方案能达到最大值。

    Code

    #define lson (o << 1)
    #define rson (o << 1 | 1)
    int Max[N << 2], c[N], d[N], n;
    void Build(int o, int l, int r) {
    	if (l == r) return (void) (Max[o] = l);
    	int mid = (l + r) >> 1;
    	Build(lson, l, mid); Build(rson, mid + 1, r);
    	Max[o] = c[Max[lson]] > c[Max[rson]] ? Max[lson] : Max[rson];
    	return ;
    }
    int Qpos(int o, int l, int r, int L, int R) {
    	if (L <= l && r <= R) return Max[o];
    	int mid = (l + r) >> 1, res = 0;
    	if (L <= mid) res = Qpos(lson, l, mid, L, R);
    	if (R > mid) {
    		int t = Qpos(rson, mid + 1, r, L, R);
    		res = c[res] > c[t] ? res : t;
    	}
    	return res;
    }
    struct data {
    	int v, c;
    	data operator + (const data &z) const {
    		if (v == z.v) return (data) {v, (c + z.c) % Mod};
    		else if (v > z.v) return (data) {v, c};
    		else return z;
    	}
    } f[N], t[N << 2], lz[N << 2];
    void pushup(int o) { t[o] = t[lson] + t[rson]; }
    void put(int o, data k) { lz[o] = lz[o] + k, t[o] = t[o] + k; }
    void pushdown(int o) {
    	if (lz[o].v != -inf) {
    		put(lson, lz[o]), put(rson, lz[o]);
    		lz[o] = (data) {-inf, 0};
    	}
    }
    void build(int o, int l, int r) {
    	lz[o] = (data) {-inf, 0};
    	if (l == r) return (void) (t[o] = f[l]);
    	int mid = (l + r) >> 1;
    	build(lson, l, mid); build(rson, mid + 1, r);
    	return pushup(o);
    }
    void Modify(int o, int l, int r, int L, int R, data k) {
    	if (L <= l && r <= R) return put(o, k);
    	int mid = (l + r) >> 1; pushdown(o);
    	if (L <= mid) Modify(lson, l, mid, L, R, k);
    	if (R > mid) Modify(rson, mid + 1, r, L, R, k);
    	return pushup(o);
    }
    data query(int o, int l, int r, int L, int R) {
    	if (L <= l && r <= R) return t[o];
    	int mid = (l + r) >> 1; data res = (data) {-inf, 0}; pushdown(o);
    	if (L <= mid) res = query(lson, l, mid, L, R);
    	if (R > mid) res = res + query(rson, mid + 1, r, L, R);
    	return res;
    }
    int L[N];
    void prework() {
    	for (int i = 1; i <= n; i++) f[i] = (data) {-inf, 0};
    	f[0] = (data) {0, 1};
    	Build(1, 1, n), build(1, 0, n);
    	priority_queue<int, vector<int>, greater<int> > q1, q2;
    	for (int i = 1; i <= n; i++) {
    		L[i] = L[i - 1], q1.push(d[i]);		
    		while (!q2.empty() && q1.top() == q2.top()) q1.pop(), q2.pop();
    		while (q1.top() < i - L[i]) {
    			q2.push(d[++L[i]]);		
    			while (!q2.empty() && q1.top() == q2.top()) q1.pop(), q2.pop();
    		}
    	}
    	return ;
    }
    void upd(int p) {
    	int o = 1, l = 0, r = n;
    	while (l < r) {
    		int mid = (l + r) >> 1;
    		pushdown(o);
    		if (p <= mid) o = lson, r = mid;
    		else o = rson, l = mid + 1;
    	}
    	t[o] = f[p] = f[p] + lz[o];
    	while (o >>= 1) pushup(o);
    }
    void solve(int l, int r) {
    	if (l == r) return upd(l);
    	int p = Qpos(1, 1, n, l + 1, r);
    	solve(l, p - 1);
    	int i = max(p, l + c[p]);
    	data now = (l <= i - c[p] - 1 ? query(1, 0, n, l, i - c[p] - 1) : (data) {-inf, 0});
    	while (i <= r && L[i] <= l && i - c[p] < p) {
    		now = now + f[i - c[p]];
    		f[i] = f[i] + (data) {now.v + 1, now.c};
    		i++;
    	}
    	if (i <= r && L[i] <= l) {
    		int ll = i, rr = r;
    		while (ll <= rr) {
    			int mid = (ll + rr) >> 1;
    			if (L[mid] <= l) ll = mid + 1;
    			else rr = mid - 1;
    		}
    		Modify(1, 0, n, i, ll - 1, (data) {now.v + 1, now.c});
    		i = ll;
    	}
    	while (i <= r && L[i] > l && L[i] < p) {
    		data res = query(1, 0, n, L[i], min(i - c[p], p - 1));
    		f[i] = f[i] + (data) {res.v + 1, res.c};
    		i++;
    	}
    	solve(p, r);
    	return ;
    }
    int main() {
    	n = gi<int>();
    	for (int i = 1; i <= n; i++)
    		c[i] = gi<int>(), d[i] = gi<int>();
    	prework();
    	solve(0, n);
    	if (f[n].v <= 0) puts("NIE");
    	else printf("%d %d
    ", f[n].v, f[n].c);
    	return 0;
    }
    
    

    「JOISC 2020 Day2」遗迹

    题目链接

    #include<bits/stdc++.h>
    
    #define LL long long
    #define RG register
    
    using namespace std;
    template<class T> T gi() {
    	T x = 0; bool f = 0; char c = getchar();
    	while (c != '-' && (c < '0' || c > '9')) c = getchar();
    	if (c == '-') f = 1, c = getchar();
    	while (c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
    	return f ? -x : x;
    }
    const int N = 650, Mod = 1e9 + 7;
    int f[N << 1][N], g[N][N];
    bool a[N << 1];
    int fpow(int a, int b) {
    	int res = 1;
    	for (; b; b >>= 1, a = 1ll * a * a % Mod)
    		if (b & 1) res = 1ll * res * a % Mod;
    	return res;
    }
    int fac[N], ifac[N];
    int C(int n, int m) {
    	if (n < m) return 0;
    	return 1ll * fac[n] * ifac[m] % Mod * ifac[n - m] % Mod;
    }
    int main() {
    	//freopen(".in", "r", stdin);
    	//freopen(".out", "w", stdout);
    	int n = gi<int>();
    	for (int i = 1; i <= n; i++) a[gi<int>()] = 1;
    	fac[0] = g[0][0] = 1;
    	for (int i = 1; i <= n; i++) fac[i] = 1ll * fac[i - 1] * i % Mod;
    	ifac[n] = fpow(fac[n], Mod - 2);
    	for (int i = n; i; i--) ifac[i - 1] = 1ll * ifac[i] * i % Mod;
    	for (int i = 1; i <= n; i++)
    		for (int j = 0; j <= i; j++) {
    			g[i][j] = g[i - 1][j];
    			if (j) (g[i][j] += 2ll * g[i - 1][j - 1] * j % Mod) %= Mod;
    			if (j > 1) (g[i][j] += 1ll * g[i - 1][j - 2] * (j - 1) % Mod * j % Mod) %= Mod;
    		}
    	int cnt0 = 0, cnt1 = 0;
    	f[2 * n + 1][0] = 1;
    	for (int i = 2 * n; i; i--)
    		if (!a[i]) {
    			for (int j = cnt0; j <= cnt1; j++)
    				f[i][j] = 1ll * f[i + 1][j] * (j - cnt0) % Mod;
    			cnt0++;
    		}
    		else {
    			for (int j = 0; j <= cnt1; j++) {
    				(f[i][j] += f[i + 1][j]) %= Mod;
    				for (int k = 1; j + k <= cnt1 + 1; k++)
    					(f[i][j + k] += 1ll * f[i + 1][j] *
    					 C(cnt1 - j, k - 1) % Mod * g[k - 1][k - 1] % Mod * (k + 1) % Mod) %= Mod;
    			}
    			cnt1++;
    		}
    	cout << 1ll * f[1][n] * fpow(fpow(2, n), Mod - 2) % Mod << endl;
    	return 0;
    }
    
    
  • 相关阅读:
    107. Binary Tree Level Order Traversal II
    103. Binary Tree Zigzag Level Order Traversal
    102. Binary Tree Level Order Traversal
    690. Employee Importance
    1723. Find Minimum Time to Finish All Jobs
    LeetCode 329 矩阵中最长增长路径
    7.2 物理内存管理
    LeetCode 面试题 特定深度节点链表
    LeetCode 100 相同的树
    npm安装包命令详解,dependencies与devDependencies实际区别
  • 原文地址:https://www.cnblogs.com/zzy2005/p/11565225.html
Copyright © 2011-2022 走看看