课前C++恶搞小程序
今天,博主给大家带来了一个坑人小程序(鼠标乱飞),可以让你的好基友的鼠标瘫痪,然后……你就被她/他揍死了,言归正传,这个程序很简单,用死循环+随机位置就可以了!下面就是我的恶搞小程序。
献上代码^_^(无伤害):
//鼠标乱飞 按Alt+F4即可解决
#include<bits/stdc++.h>
#include<windows.h>
using namespace std;
int main()
{
while(1)
{
SetCursorPos(rand()%1000,rand()%1000);
}
}
注意是C++哦,别搞混成其他语言了。哦对了如果你想让鼠标不在乱飘的话请按下Alt+F4或Alt+Fn+F4这个按你们电脑的情况来看啦!!!
前言
抱歉,因为开学事情比较多,有一周没有更新了。
题目
题目描述
小T
是一名质量监督员,最近负责检验一批矿产的质量。这批矿产共有 n 个矿石,从 1 到 n 逐一编号,每个矿石都有自己的重量 wi 以及价值 vi 。检验矿产的流程是:
-
给定m 个区间 [li,ri];
-
选出一个参数 W;
-
对于一个区间 [li,ri],计算矿石在这个区间上的检验值 yi:
yi=j=li∑ri[wj≥W]×j=li∑ri[wj≥W]vj
其中 j 为矿石编号。
这批矿产的检验结果 y 为各个区间的检验值之和。即:i=1∑myi
若这批矿产的检验结果与所给标准值 s 相差太多,就需要再去检验另一批矿产。小T
不想费时间去检验另一批矿产,所以他想通过调整参数 W 的值,让检验结果尽可能的靠近标准值 s,即使得 ∣s−y∣ 最小。请你帮忙求出这个最小值。
输入格式
第一行包含三个整数 n,m,s,分别表示矿石的个数、区间的个数和标准值。
接下来的 n 行,每行两个整数,中间用空格隔开,第 i+1 行表示 i 号矿石的重量 wi 和价值 vi。
接下来的 m 行,表示区间,每行两个整数,中间用空格隔开,第 i+n+1 行表示区间 [li,ri] 的两个端点 li 和ri。注意:不同区间可能重合或相互重叠。
输出格式
一个整数,表示所求的最小值。
输入输出样例
输入 #1
5 3 15
1 5
2 5
3 5
4 5
5 5
1 5
2 4
3 3
输出 #1
10
说明/提示
【输入输出样例说明】
当 W 选 44 的时候,三个区间上检验值分别为 20,5,020,5,0 ,这批矿产的检验结果为 2525,此时与标准值 S 相差最小为 1010。
【数据范围】
对于 10% 的数据,有 1≤n,m≤10;
对于 30%的数据,有 1≤n,m≤500 ;
对于 50% 的数据,有 1≤n,m≤5,000;
对于 70% 的数据,有 1≤n,m≤10,000 ;
对于 100%的数据,有 1≤n,m≤200,000,0<wi,vi≤106,0<s≤1012,1≤li≤ri≤n 。
解题思路
简述:
本题是一个比较明显的二分题,显然可以看出来这个标准值S是可以二分的,之后如果暴力O(nmlog1e6)就是50分。
但我们显然不用暴力,这里我们可以先预扫一遍数组,并用前缀和存w和v,之后再一个O(m)暴力判断就可以了。
和大于标准时加大l以加大mid,小于时减少r。
并一定要注意l和r的初始大小,l为所有值中最小-1,虽然貌似不减也可以过,r为最大值+1。
如果看懂了,就没必要看下面的了。
由于我们并不清楚要求的W的值,但是我们知道W的值不超过矿石中价值最大的,如果W大于了矿石中价值最大的,那么Y的值为0,无法达到最优解。
因此,很容易就能想到在确定W的值要用二分的方法。
在分析这道题的时候,我们很容易知道Y的值是满足单调性的,当W的值越大,Y的值越小,因为W越大,能够选的矿石就越少。
所以我们把得到的Y值作为判断条件,如果Y比S小,就说明检验值了,而W取大了。每次更改W的同时给ans取最小值。
那么Y又应该怎么求出呢?题目中n,m最大有2*10^5,
如果暴搜肯定超时,因此我们需要在枚举W的时候预处理。遍历w数组,保存满足条件的v和个数的前缀和。然后再遍历一遍要求的区间。
AC
#include <bits/stdc++.h>
using namespace std;
struct stone
{
long long w;
long long v;
};
bool compare(struct stone s1, struct stone s2)
{
return s1.w < s2.w;
}
int main()
{
long long n, m, s;
cin >> n >> m >> s;
struct stone rock[200001];
struct stone rock_list[200001];
for (int i = 1; i <= n; i++)
{
cin >> rock[i].w >> rock[i].v;
rock_list[i].w = rock[i].w;
rock_list[i].v = rock[i].v;
}
long *l = new long[m], *r = new long[m];
for (int i = 0; i < m; i++)
{
cin >> l[i] >> r[i];
}
sort(rock_list + 1, rock_list + n, compare);
long mini = 0x3f3f3f3f3f3f3f3f;
int left = 0, right = n, mid = (right + left) / 2;
while (left <= right)
{
struct stone *rock_temp = new struct stone[n + 1];
long *num = new long[n + 1];
num[0] = 0;
rock_temp[0].v = 0;
rock_temp[0].w = 0;
for (int i = 1; i <= n; i++)
{
if (rock[i].w >= rock_list[mid].w + 1)
{
rock_temp[i].v = rock[i].v + rock_temp[i - 1].v;
num[i] = num[i - 1] + 1;
}
else
{
rock_temp[i].v = rock_temp[i - 1].v;
num[i] = num[i - 1];
}
}
long long y = 0;
for (int i = 0; i < m; i++)
{
long l1 = l[i];
long r1 = r[i];
y += (num[r1] - num[l1 - 1]) * (rock_temp[r1].v - rock_temp[l1 - 1].v);
}
if (llabs(y - s) < mini)
{
mini = llabs(y - s);
}
if (y < s)
{
right = mid - 1;
}
else if (y == s)
{
break;
}
else if (y > s)
{
left = mid + 1;
}
mid = (left + right) / 2;
}
cout << mini;
return 0;
}
结尾
希望大家多多关注!!!
如果你能支持一下我,我十分感谢!!!
如果有人想在洛谷上做题,可以点下方链接:
如果你喜欢或想了解一下其他的算法,可以看看以下这些:
洛谷指南
题目详解系列(部分):
游戏系列:
C++讲解系列(算法):
C++:第十二讲DFS深搜(二)_c++匿名函数dfs-CSDN博客
前缀和与差分:
贪心:
C++讲解系列(基础入门):
排序:
函数:
C++第6讲max和min函数_c++ min函数-CSDN博客
for循环&数组:
if语句&else语句及运算:
C++第三讲:C++中的逻辑运算符及if else语句-CSDN博客
基础:
欢迎收看,希望大家能三连!
最后认识一下,我是爱编程的喷火龙廖,我们有缘再见!