板刷计划:ARC073

前言:ATCODER的题是真的硬阿。思维量大…虐杀我这种无智商选手。

A.模拟,略.


B.暴力枚举

题目大意:

给你一个容量为w( w ≤ 1 e 9 w \leq 1e9 w1e9)的背包.现在有n( n ≤ 100 n \leq 100 n100)个物品,每个物品有体积 w i w_i wi 和 价值 v i ( w i , v i ≤ 1 e 9 ) v_i(w_i,v_i \leq 1e9) vi(wi,vi1e9).现在要让你最大化背包价值. 体积 w i ∈ [ w 1 , w 1 + 3 ] w_i \in [w_1,w_1+3] wi[w1,w1+3]

题目思路:

一个NPC问题。但是给定了体积的值域范围。不难想到对物品按体积大小分成4类再按价值从大到小排序.之后直接枚举每种体积的物品选多少个.跑个dfs即可。这样就包含了所有可能情况.

复杂度: O ( ( n 4 ) 4 ) O((\frac{n}{4})^4) O((4n)4)


C.究极思维,贪心.

题目大意:

给你n( n ≤ 1 e 5 n \leq 1e5 n1e5)个二元组 ( x i , y i ) (x_i,y_i) (xi,yi)。现在有两个集合A,B.你需要将所有二元组的其中一个放入集合A或B里。那么另外一个就会放入到另外一个集合里去。现在让你最小化下式:
( m a x A − m i n A ) ∗ ( m a x B − m i n B ) (max_A-min_A) * (max_B-min_B) (maxAminA)(maxBminB)

题目思路:

方法一 :正解

不难发现,二元组的最小值MI以及最大值MX一定存在于A,B集合中的一个。即一定会在上式中出现.

那么根据他们出现的情况讨论一下:

1.当 MI,MX 一个属于A,一个属于B.(具体是哪个不重要,因为对称)。假设: M I ∈ A , M X ∈ B MI \in A ,MX \in B MIAMXB

很显然,现在我们的策略就是:将每一个二元组中 较小的给A集合。 较大的给B集合.这样一定是最优的。

注:当时到这里我就卡住了,无法继续往下推了。。

2.当 MI,MX 同时属于A/B(具体是哪个不重要,因为对称)。假设: M I , M X ∈ A MI,MX\in A MI,MXA

由于 ( m a x A − m i n A ) (max_A-min_A) (maxAminA)已经确定,现在我们要做的事情就是最小化 ( m a x B − m i n B ) (max_B-min_B) (maxBminB).

这里的思路是:枚举 m i n B min_B minB. 假设最优解时 m i n B = x i min_B=x_i minB=xi,那么那些 【二元组较小值 小于 x i x_i xi】的二元组的较大值y要给B集合.

显然对x( x < y x < y x<y)从小到大排序,然后从小到大枚举x以及其后缀x就可以。为什么后缀全要选,因为我们人为规定了 x < y x < y x<y.所以后缀二元组中我们一定要选x.至于x的前缀二元组一定要选y,是因为必须要选才能满足 m i n B = x i min_B=x_i minB=xi

这里有个很简单的实现方式,用multiset,然后算完情况1后对二元组排序。直接模拟交换二元组即可。

AC代码:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define pii pair<int,int>
#define pll pair<ll,ll>
#define pb push_back
#define mp make_pair
const int maxn = 2e5 + 5;
const int mod = 1e9 + 7;
pii a[maxn];
multiset<ll> A , B;
int main()
{
    
    
    ios::sync_with_stdio(false);
    int n; cin >> n;
    for (int i = 1 ; i <= n ; i++){
    
    
        cin >> a[i].first >> a[i].second;
        if (a[i].first > a[i].second) swap(a[i].first , a[i].second);
        A.insert(max(a[i].first,a[i].second));
        B.insert(min(a[i].first,a[i].second));
    }
    ll ans = (*(--A.end()) - *(A.begin())) * (*(--B.end()) - *(B.begin()));
    sort(a + 1 , a + 1 + n);
    for (int i = 1 ; i <= n ; i++){
    
    
        A.erase(A.find(a[i].second));
        B.erase(B.find(a[i].first));
        A.insert(a[i].first);
        B.insert(a[i].second);
        ans = min (ans , (*(--A.end()) - *(A.begin())) * (*(--B.end()) - *(B.begin())));
    }
    cout << ans << endl;
    return 0;
}

方法二 :随机化 + 贪心

离谱


D.dp + 线段树

待补.

题目大意:
题目思路:

猜你喜欢

转载自blog.csdn.net/qq_35577488/article/details/108965015
073
arc