• 【SNUT集训1】排序 二分 前缀和 差分(6 / 16)


    目录

    P1094 [NOIP2007 普及组] 纪念品分组 - 排序+贪心+双指针

    P1571 眼红的Medusa - 哈希表

    P1678 烦恼的高考志愿

    P1024 [NOIP2001 提高组] 一元三次方程求解

    1、二分法

    2、暴力

    P7585 [COCI2012-2013#1] LJUBOMORA - 二分

    P4552 [Poetize6] IncDec Sequence- 差分思维玄学题


    P1094 [NOIP2007 普及组] 纪念品分组 - 排序+贪心+双指针

    [NOIP2007 普及组] 纪念品分组 - 洛谷

    1. import java.util.*;
    2. public class Main
    3. {
    4. public static void main(String[] args)
    5. {
    6. Scanner sc=new Scanner(System.in);
    7. int target=sc.nextInt();
    8. int n=sc.nextInt();
    9. int[] a=new int[n];
    10. for(int i=0;i
    11. Arrays.sort(a);
    12. int res=0;
    13. int l=0,r=n-1;
    14. while(l<=r)
    15. {
    16. if(a[l]+a[r]<=target)
    17. {
    18. l++;r--;res++;
    19. }else
    20. {
    21. r--;res++;
    22. }
    23. }
    24. System.out.print(res);
    25. }
    26. }

    P1571 眼红的Medusa - 哈希表

    眼红的Medusa - 洛谷

    1. import java.util.*;
    2. public class Main
    3. {
    4. public static void main(String[] args)
    5. {
    6. Scanner sc=new Scanner(System.in);
    7. int n=sc.nextInt(),m=sc.nextInt();
    8. int[] a=new int[n];
    9. Set s=new HashSet<>();
    10. for(int i=0;i
    11. for(int i=0;i
    12. {
    13. int x=sc.nextInt();
    14. s.add(x);
    15. }
    16. for(int i=0;i
    17. if(s.contains(a[i])) System.out.print(a[i]+" ");
    18. }
    19. }

    P1678 烦恼的高考志愿

    烦恼的高考志愿 - 洛谷

    c++版

    思路:

    朴素思路是:每个人的成绩和每个学校作差 取最小值

    但是这样时间复杂度是O(m*n) 会tle

    所以我们使用二分优化

    • 先将所有学校分数线排序
    • 找出学校分数线中最后一个比该人分数小的分数
    • 最后取 min(最后一个比该分数小,第一个比该分数大)
    • 需要加一个特判:当所有学校的分数都比该分数大时,直接取最小学校分数线-该生成绩
    1. #include
    2. using namespace std;
    3. int main()
    4. {
    5. int m,n;
    6. cin>>m>>n;
    7. int a[100100],b[100100];
    8. long long res=0;
    9. for(int i=0;i>a[i];
    10. for(int i=0;i>b[i];
    11. sort(a,a+m);
    12. for(int i=0;i
    13. {
    14. int l=0,r=m-1;
    15. while(l
    16. {
    17. int mid=(l+r+1)>>1;
    18. if(a[mid]<=b[i]) l=mid;
    19. else r=mid-1;
    20. }
    21. if(b[i]<=a[l]) res+=a[l]-b[i];
    22. else res+=min(abs(b[i]-a[l+1]),abs(b[i]-a[l]));
    23. }
    24. cout<
    25. }

    java写了超时 栓Q

    1. package text;
    2. import java.util.*;
    3. public class Text //主类
    4. {
    5. public static void main(String[] args)
    6. {
    7. Scanner sc=new Scanner(System.in);
    8. int m=sc.nextInt(),n=sc.nextInt();
    9. long res=0;
    10. int[] a=new int[m];
    11. int[] b=new int[n];
    12. for(int i=0;i
    13. for(int i=0;i
    14. Arrays.sort(a);
    15. for(int i=0;i
    16. {
    17. int l=0,r=m-1;
    18. while(l
    19. {
    20. int mid=l+r+1>>1;
    21. if(a[mid]<=b[i]) l=mid;
    22. else r=mid-1;
    23. }
    24. if(b[i]<=a[l]) res+=a[l]-b[i];
    25. else
    26. res+=Math.min(Math.abs(b[i]-a[l+1]),Math.abs(b[i]-a[l]));
    27. }
    28. System.out.print(res);
    29. }
    30. }

    P1024 [NOIP2001 提高组] 一元三次方程求解

    [NOIP2001 提高组] 一元三次方程求解 - 洛谷

    1、二分法

    • 三个答案都在[-100,100]范围内
    • 两个根的差的绝对值>=1,保证了每一个大小为1的区间里至多有1个解
    • 枚举每个长度为1的区间
    • 如果该端点 f(l) 为0,则直接输出该解(注意不能判断f(r)   因为区间内至多1个解)
    • 如果该区间左右端点的 f(l) * f(r) <0  说明该区间内存在解
    • 此时在这个区间内进行二分查找该解并输出
    1. #include
    2. using namespace std;
    3. double a,b,c,d;
    4. double f(double x)
    5. {
    6. return a*x*x*x+b*x*x+c*x+d;
    7. }
    8. int main()
    9. {
    10. int sum=0;
    11. double l,r,mid,f1,f2;
    12. cin>>a>>b>>c>>d;
    13. for(int i=-100;i<100;i++)
    14. {
    15. l=i;
    16. r=i+1;
    17. f1=f(l);
    18. f2=f(r);
    19. if(!f1) //如果端点是零点 直接输出
    20. {
    21. printf("%.2lf ",l);
    22. sum++;
    23. }
    24. if(f1*f2<0)
    25. {
    26. while(r-l>=0.001)
    27. {
    28. mid=(l+r)/2;
    29. if(f(mid)*f(r)<=0) l=mid;
    30. else r=mid;
    31. }
    32. printf("%.2lf ",l);
    33. sum++;
    34. }
    35. if(sum==3) break;
    36. }
    37. }

    2、暴力

    1. #include
    2. using namespace std;
    3. double a,b,c,d;
    4. int main()
    5. {
    6. int sum=0;
    7. cin>>a>>b>>c>>d;
    8. for(double i=-100;i<=100;i+=0.001)
    9. {
    10. if(fabs(a*i*i*i+b*i*i+c*i+d)<0.0001)
    11. printf("%.2lf ",i);
    12. if(sum==3) break;
    13. }
    14. }

    P7585 [COCI2012-2013#1] LJUBOMORA - 二分

    [COCI2012-2013#1] LJUBOMORA - 洛谷

    思路:

    当嫉妒值越大,能分到弹珠的孩子越少,嫉妒值越小,能分到弹珠的孩子越多

    得出——嫉妒值有单调性,可以二分

    • 首先设嫉妒值为mid,边界 l=1,r=max(g[i]) 最大弹珠数
    • 对于第 i 种弹珠,能分给的孩子数为 gimid" role="presentation">gimid ,所以最后孩子数cnt=i=1Mgimid" role="presentation">cnt=i=1Mgimid
    • 如果cntn" role="presentation">cntn,则当前的mid太大,分到弹珠的孩子太少,r=mid
    • 如果cnt>n" role="presentation">cnt>n,则当前的mid太小,分到弹珠的孩子太多,l=mid+1
    1. #include
    2. #define ll long long
    3. using namespace std;
    4. const int M=3e5+10;
    5. int g[M],m,n;
    6. bool check(int x)
    7. {
    8. int cnt=0;
    9. for(int i=0;i
    10. {
    11. cnt+=g[i]/x;
    12. if(g[i]%x) cnt++; //如果不能均分 还要多分给一个小朋友
    13. }
    14. return cnt<=n;
    15. }
    16. int main()
    17. {
    18. cin>>n>>m;
    19. int maxx=-1;
    20. for(int i=0;i
    21. {
    22. cin>>g[i];
    23. maxx=max(maxx,g[i]);
    24. }
    25. int l=1,r=maxx;
    26. while(l
    27. {
    28. int mid=l+r>>1;
    29. if(check(mid)) r=mid;
    30. else l=mid+1;
    31. }
    32. cout<
    33. return 0;
    34. }

    P4552 [Poetize6] IncDec Sequence- 差分思维玄学题

    [Poetize6] IncDec Sequence - 洛谷

    思路:

    这题可以转化为求出原数列的差分数组b,最后使得 \large b[2]\sim b[n]=0

    题目中对数组a的操作,相当于每次能选出 \large b_{1},b_{2},...,b_{n} 中任意两个数,一个+1,一个-1

    • x= b中所有正数之和
    • y= b中所有负数之和的绝对值
    • 我们需要先正负抵消,这时剩下最后一个数,再单独把这个数消成0
    • 所以操作数就是 max(x,y)

    • 求方案数 也就是求\large b_{i}的可能数
    • 完成以上操作后得到的b差分数组就是 \large b=\left \{ b_{1},0,...,x-y \right \}
    • 要把 x-y 消0,需要 \large \left | x-y \right | 步
    • 所以b[1]会有 \large \left | x-y \right |+1 种方案
    1. #include
    2. using namespace std;
    3. const int N=1e5+10;
    4. long long a[N],zheng,fu;
    5. int main()
    6. {
    7. int n;
    8. cin>>n;
    9. for(int i=1;i<=n;i++) cin>>a[i];
    10. for(int i=2;i<=n;i++)
    11. {
    12. int x=a[i]-a[i-1];
    13. if(x>0) zheng+=x;
    14. else fu+=abs(x);
    15. }
    16. cout<<max(zheng,fu)<abs(zheng-fu)+1;
    17. return 0;
    18. }

  • 相关阅读:
    Java web(七):Vue&Element
    esp32 arduino使用多个串口时如何查看serial1,serial2所对应的引脚定义
    Java——数组的使用
    Nginx之正则表达式、location匹配及rewrite重写
    本地代码上传到gitlab
    模糊查询like用法实例(Bee)
    【Linux】 - Linux中查看命令文档的命令
    湖北省支持企业技术创新发展项目支持对象、奖励和申报流程、要求、材料
    Spring实战系列(二)Bean装配
    统计学习方法 | 朴素贝叶斯法
  • 原文地址:https://blog.csdn.net/weixin_61639349/article/details/127934419