zoukankan      html  css  js  c++  java
  • [省选联考 2021 A/B 卷] 卡牌游戏

    垃圾福建垫底选手来看看这题。
    大家怎么都写带 \(log\) 的。
    我来说一个线性做法好了。
    那么我们考虑枚举 \(k\) 作为翻转完的最小值。
    那么构造出一个满足条件的操作,我们在 \(a_i\) 中查询一个最大的位置使 \(a_i < k\) ,那么 \(a_1\)\(a_i\) 都要进行翻转,且 \(b_1 到 b_i > k\),那么这样做的次数是 \(i\) 或者 \(i - 1\)(考虑\(k\)\(b\)且对应的\(a\)在需要翻转的区间里)的。
    那么考虑对这个 \(k\) 求出一个最小的最大值\(z\),同样的我们在\(a_i\)中查询一个最小的位置使\(a_i > z\),那么\(a_i\)\(a_n\)都要进行翻转,且 \(b_i\)\(b_n > k\),且 \(b_i\)\(b_n < z\) ,那么这样做的次数是 \(n - i + 1\) 或者 \(n - i\) (考虑 \(z\)\(b\) 且对应的 \(a\) 在需要翻转的区间里)的,两边次数加起来不超过 \(m\)
    我们考虑对这几个条件进行分析一下,首先 \(i\) 对于 \(z\) 减小是单调的,由于 \(min\) 只能下降不能上升, \(max\) 只能上升不能下降,那么对于\(z\)下降来说,他的条件会越来越苛刻。
    又因为我们从小到大枚举 \(k\) ,用来满足 \(k\) 的次数会单调不降,那么我们发现,对于一个 \(z\) ,他的所有条件即 \(b_i\)\(b_n > k\),且 \(b_i\)\(b_n < z\) ,次数和小于 \(m\) ,在 \(k\) 上升都具有单调性,感性分析一下,在 \(k\) 上升时, \(z\) 具有单调不降的性质。
    那么我们只要对 \(k = 1\) 一个 \(log\) 求出对应的 \(z\) ,再进行双指针,就可以做到 \(O(n)\) 了。

    upd:发现自己的这个做法挺难写的,应该考虑计算的时候,也扩展到整个序列就好做了。

    [省选联考 2021 A/B 卷] 卡牌游戏
    #include <bits/stdc++.h>
    using namespace std;
    struct hehe{
    	long long a, num;
    	int op;
    	bool operator < (hehe b) const
    	{
    		return a < b.a;
    	}
    }a[2000001];
    bool used[2000001];
    int main()
    {
    	// freopen("card3.in", "r", stdin);
    	int n, k;
    	cin >> n >> k;
    	for(int i = 1; i <= n; i++)
    	{
    		scanf("%d", &a[i].a);
    		a[i].num = i;
    		a[i].op = 1;
    	}
    	for(int i = 1; i <= n; i++)
    	{
    		scanf("%d", &a[n + i].a);
    		a[i + n].num = i;
    		a[i].op = 1;
    	}
    	sort(a + 1, a + n * 2 + 1);
    	int l = 0, r = n * 2 + 1, now = 0;
    	while(!used[a[l + 1].num] && now + a[l + 1].op <= k) now += a[l + 1].op, used[a[l + 1].num] = 1, l++;
    	while(!used[a[r - 1].num] && now + a[r - 1].op <= k) now += a[r - 1].op, used[a[r - 1].num] = 1, r--;
    	long long ans = 1000000000000;
    	while(l >= 0)
    	{
    		ans = min(a[r - 1].a - a[l + 1].a, ans);
    		used[a[l].num] = 0;
    		now -= a[l].op;
    		l--;
    		while(!used[a[r - 1].num] && now + a[r - 1].op <= k) now += a[r - 1].op, used[a[r - 1].num] = 1, r--;
    	}
    	cout << ans << endl;
    }
    
  • 相关阅读:
    体检套餐管理系统
    Altium Designer9.4局域网内冲突的问题
    关于ARM Linux下的SD卡及U盘的挂载问题
    mkimage command not found – U-Boot images will not be built
    Xilinx------BUFG,IBUFG,BUFGP,IBUFGDS等含义以及使用
    linux文件压缩解压命令
    VIVADO 入门之仿真与逻辑分析仪使用
    Linux自动运行应用程序
    ZYNQ学习之二-EMIO
    inux grep 命令 搜索含有"zynq"字符的文件
  • 原文地址:https://www.cnblogs.com/dixiao/p/14649909.html
Copyright © 2011-2022 走看看