1 条题解

  • 0
    @ 2025-4-16 16:36:29

    如果阿兔开始攻击某一只兔崽子,那么阿兔肯定会一直攻击它直到它被制服。那么每只兔崽子的制服时间为:ti=hi/kt_{i} = \lceil h_{i}/k \rceil

    接下来我们考虑比较相邻两只兔崽子 iijj 的交换贡献变化。交换对于 ii 前面和 jj 后面 的贡献都是一致,我们只考虑改变部分。

    $$tot1 = t_{i} * a_{i}+t_{i} * a_{j}+t_{j} * a_{j} \\ tot2 = t_{j} * a_{j}+t_{j} * a_{i}+t_{i} * a_{i} \\ tot1-tot2 = t_{i} * a_{j}-t_{j} * a_{i} $$

    我们发现交换后贡献的变化为 tot1tot2tot1 - tot2 ,那么我们在交换时使 tot1tot2>0tot1 - tot2 > 0 即可降低贡献。所以排序规则为:tiaj>tjait_{i} * a_{j} > t_{j} * a_{i} 。我们排序后线性计算即可。

    时间复杂度:O(nlogn)O(nlogn)

    const int maxn = 2e5 + 7, mod = 1e9 + 7;
    int n, k, q;
    struct node
    {
    	int h, a;
    	bool operator<(const node &o) const
    	{
    		return h * o.a < o.h * a;
    	}
    } ha[maxn];
    
    void solve()
    {
    	cin >> n >> k;
    	int sum = 0;
    	for (int i = 1; i <= n; i++)
    	{
    		cin >> ha[i].h >> ha[i].a;
    		ha[i].h = (ha[i].h + k - 1) / k;
    		sum = (sum + ha[i].a) % mod;
    	}
    
    	sort(ha + 1, ha + 1 + n);
    
    	int now = 0, ans = 0;
    	for (int i = 1; i <= n; i++)
    	{
    		ans = (ans + ha[i].h * sum) % mod;
    		sum = (sum - ha[i].a + mod) % mod;
    	}
    	cout << ans << endl;
    }
    
    • 1

    信息

    ID
    16
    时间
    1000ms
    内存
    256MiB
    难度
    10
    标签
    递交数
    1
    已通过
    1
    上传者