首页 > 其他分享 >刷题笔记:Luogu P1083 借教室

刷题笔记:Luogu P1083 借教室

时间:2023-05-17 22:48:15浏览次数:59  
标签:Luogu ll sum2 sum1 ge P1083 include check 刷题

题目传送门

让结果最接近\(s\)值,显然我们要二分\(w\),check的写法可以直接暴力模拟,如果check(mid)<s则将r右移(通过读公式可以知道\(w\)越小检验值\(y\)就越大)

但是这样会TLE,再读一下柿子:
\(y_i=\sum\limits_{j=l_i}^{r_i}[w_j \ge W] \times \sum\limits_{j=l_i}^{r_i}[w_j \ge W]v_j\)
显然可以前缀和优化,每次check前分别前缀和记录一下\(sum1=\sum\limits_{j=l_i}^{r_i}[w_j \ge W]\)和$ sum2=\sum\limits_{j=l_i}^{r_i}[w_j \ge W]v_j$。
这样check过程中可以直接求 \(sum1,sum2\),\(sum1\times sum2\)就是检验值\(y_i\),另设一个变量ans+=sum1*sum2即可

通过这样的优化,对检验值\(y_i\)的计算我们每次check只需要计算一次(每次check \(w\)是唯一的,即\(y_i\)是唯一的)大大提高了效率

代码实现
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#define N 1000000
#define ll long long
#define INF 0x3f3f3f3f3f
using namespace std;
ll n,m,s;
ll ans = INF;
ll l[N],r[N],w[N],v[N]; 
ll l_sum1[N],l_sum2[N];
void update(ll lll,ll rr,ll d,ll d1)
{
    l_sum1[lll] ++;
    l_sum1[rr+1] --;
    l_sum2[lll] += d;
    l_sum2[rr+1] -= d;
}
bool check(ll x)
{
    memset(l_sum1,0,sizeof(l_sum1));
    memset(l_sum2,0,sizeof(l_sum2));
    ll check_num = 0;
    for(int i=1;i<=n;i++)
    {
        if(w[i] >= x) 
        {
            l_sum1[i] = l_sum1[i-1]+1;
            l_sum2[i] = l_sum2[i-1]+v[i];
        }
        else
        {
            l_sum1[i] = l_sum1[i-1];
            l_sum2[i] = l_sum2[i-1];
        }
    }
    for(ll i = 1;i <= m;i ++)
    {
        ll c1 = 0,c2 = 0;
        c1 = l_sum1[r[i]] - l_sum1[l[i]-1];
        c2 = l_sum2[r[i]] - l_sum2[l[i]-1];
        check_num += c1*c2;
    }
    if(abs(check_num-s) < ans) ans = abs(check_num-s);
    return check_num >= s;
}
int main()
{
    scanf("%lld%lld%lld",&n,&m,&s);
    for(ll i=1;i<=n;i++)
    {
        scanf("%lld%lld",&w[i],&v[i]);
    }
    for(ll i =1;i<=m;i++) scanf("%lld%lld",&l[i],&r[i]);
    ll l = INF,r = 0;
    for(ll i =1;i<=n;i++)
    {
        l = min(l,w[i]);
        r = max(r,w[i]);
    }
    while(l <= r)
    {
        ll mid = (l+r+1)/2;
        if(check(mid) ) l = mid+1;
        else r = mid -1;
    }
    cout<<ans<<endl;
  //  cout<<min(abs(check(ans+1) - s),abs(check(ans) - s))<<endl;
    return 0;
}

标签:Luogu,ll,sum2,sum1,ge,P1083,include,check,刷题
From: https://www.cnblogs.com/SXqwq/p/17410551.html

相关文章

  • 2023-05-17 刷题
    算法题目1:【Mid】47.全排列II思路分析:将原问题转换成子问题,先不考虑重复元素,例如P{1,2,3}={"1"+P{2,3},"2"+P{1,3},"3"+P{1,2}}。之后再考虑重复元素。怎么枚举?枚举每个位置可以填哪些数。【这种枚举方式能保证字典序,除此外,还有一种,枚举每个数可以放到哪个位置上,......
  • 刷题笔记:P4452 [差分]
    题目传送门:https://www.luogu.com.cn/problem/P4552一道非常巧妙的差分。我们先来讲一下样例:原数组:1122差分后:1010这时,我们发现,若满足数组中所有数都相等,则必须将差分数组除第一位以外的数都变成0我们怎么用最小的次数将差分数组变成零呢?这个样例不算明显,我们再造一......
  • luogu P8340 [AHOI2022] 山河重整
    题面传送门牛逼题。solution首先来推一推性质。假设我们现在有一个合法的集合,覆盖了\([1,S]\),显然新加进去的数\(i\)不能\(\geqS+2\),而如果\(\leqS+1\)那么\([1,i+S]\)显然可以被覆盖到。因此有一个\(O(n^2)\)的dp:设选到了第\(i\)个数,总和为\(j\),要求\(j\geq......
  • Luogu P5520 [yLOI2019] 青原樱
    考虑先不种花,先算出“花之间空位的可行方案数”\(tot\),乘上花的排列的贡献就能算出答案,即\(tot\timesm!\)为答案所以只需算出“花之间空位的可行方案数”能发现,设\(x_i\)为第\(i\)朵花与第\(i-1\)朵花之间空位的数量,其中设第\(0\)朵花在\(0\)的位置,则发现会有以......
  • luogu P4690 [Ynoi2016] 镜中的昆虫 题解
    P4690[Ynoi2016]镜中的昆虫题解题意维护一个长为 \(n\) 的序列 \(a_i\),有 \(m\) 次操作。将区间 \([l,r]\) 的值修改为 \(x\)。询问区间 \([l,r]\) 出现了多少种不同的数,也就是说同一个数出现多次只算一个。题解感觉这道题还是比较有意思的,像是一堆套路......
  • 算法刷题系列之移除元素:快慢指针技巧
    题目+日期移除元素2023年5月14日17点50分基础知识暴力解法这个题目暴力的解法就是两层for循环,一个for循环遍历数组元素,第二个for循环更新数组。双指针法(快慢指针法)通过一个快指针和慢指针在一个for循环下完成两个for循环的工作。定义快慢指针快指针:寻找新数组的元......
  • pwn刷题笔记
    jarvisoj_level2(ret2text)checksec检查保护机制,开启了NX。vulnerable_function函数处存在栈溢出漏洞:buf只能存放0x88个字节,但可以读入0x100个字节。system函数plt地址:0x8048320ida查看字串,“/bin/sh”地址:0x804A024构造payload#!/usr/bin/envpython3frompwnimport*io......
  • MISC刷题心得 与百度,谷歌,github语法总结
    MISC介绍:MISC,中文即杂项,包括隐写,数据还原,脑洞、社会工程、压缩包解密、流量分析取证、与信息安全相关的大数据等。竞赛过程中解MISC时会涉及到各种脑洞,各种花式技巧,主要考察选手的快速理解、学习能力以及日常知识积累的广度、深度。misc几种常见格式文件头:png:89504E47jpg:FFD......
  • OJ刷题之旅
    题目描述wzazzy先将天上n个星星排成一排,起初它们都是暗的。他将挥动n次魔法棒,第i次挥动会将编号为i的正整数倍的星星的亮暗反转,即亮的星星转暗,暗的星星转亮。wzazzy想问,最终会有多少个星星依旧闪亮在天空。输入一个整数n,含义请见题目描述。1<=n<=1e18输出一个整数ans,即n次操......
  • LeetCode 刷题 —— 辅助栈
     42. 接雨水classSolution{publicinttrap(int[]height){intres=0;Stack<Integer>leftWallStack=newStack();intlen=height.length;leftWallStack.push(0);for(inti=1;i<len;i++){......