D.Fight against involution
- 题意:给出多名学生每篇论文需要完成的字数区间,然后起初按照右区间的字数将学生进行排名(字数越多,排名越前),但是现在题目的要求就是这些学生很“卷”,希望写的论文字数近可能的少,然后排名又要不能低于原先的排名(可以高于),然后按照上诉要求计算出所有学生需要写的最少字数之和。
- 思路:区间贪心
- 解析:首先需将右区间从小到大进行排序,若右区间相等,则左区间按从大到小排序,因为我们需要满足排名不能低于原先排名,所以当右区间相同则意味着这些学生原先的排名应当一样,若左区间取小值,则在右区间相同的其他学生左值则取不到这个小值(若不按这个小值取,则他们的排名就不相等,就不能满足之前相等的条件),当右区间ri, ri + 1不同时,这时要取max(li + 1, 至目前为止左区间最大值),因为必须保证li + 1不能小于之前的取值(不然不能保证他之前的地位),下面举例说明:
5
1 3
3 8
2 3
4 6
5 6
排序后:
2 3
1 3
5 6
4 6
3 8
模拟过程:第一次取w = 2, 接着因为2 > 1,所以仍然取w = 2,接着因为6 > 3,所以取max(5, 2) = 5,那么此时w = 5,同理下一个w = 5,但接下来我们发现8 > 6,若我们取w = 3(其左区间),则不能满足这个学生原先的排名(rank1),所以我们可以最小只能取w = 5(真的很卷),这时候尽管(5, 6)与(4, 6)这两个学生排名与(3, 8)这个学生一样(均为rank1),但满足题意要求:不低于原先排名。
- 代码:
#include<iostream>
#include<algorithm>
using namespace std;
const int N = 1e5 + 5;
struct Grade
{
int l, r;
}g[N];
int n, maxl = 0;
long long res = 0;
bool cmp(Grade a, Grade b)
{
if(a.r != b.r) return a.r < b.r;
return a.l > b.l;
}
int main()
{
cin >> n;
for(int i = 1; i <= n; i++) cin >> g[i].l >> g[i].r;
sort(g + 1, g + n + 1, cmp);
res = g[1].l, maxl = g[1].l;
for(int i = 2; i <= n; i++)
{
if(g[i].r == g[i-1].r) res += maxl;
else
{
maxl = max(g[i].l, maxl);
res += maxl;
}
}
cout << res << endl;
return 0;
}
- 题意:给出x、y(y < x),进行操作x = x ^ a(0 <= a < x),经过d(0 <= d <= 5)次后 x = y,求d。
- 性质:经过观察发现,x ^ y = z, x ^ z = y。
- 解析:tmp = x ^ y。
若tmp > x,则x ^ y = tmp(第一次把y看作a),接着X =tmp,这时候tmp(X) ^ x(初始的x,第二次把x看作a),则可使得X = y。
否则,则可把tmp看作a,x ^ tmp = y,一次则可使x = y。
- 代码:
#include<iostream>
using namespace std;
typedef long long ll;
ll x, y, tmp;
int main()
{
cin >> x >> y;
tmp = x ^ y;
if(tmp > x) cout << "2" << endl << y << " " << x << endl;
else cout << "1" << endl << tmp << endl;
return 0;
}