• D. Divide and Summarize(BFS+二分+预处理)


    Problem - 1461D - Codeforces

    迈克收到一个长度为n的数组作为生日礼物,决定测试一下它的漂亮程度。

    如果有一种方法可以通过一定数量(可能是零)的切片操作得到一个元素总和为si的数组,那么这个数组将通过第i次漂亮度测试。


    一个数组的切分操作是以如下方式进行的。

    假设mid=⌊max(array)+min(array)2⌋,其中max和min-是寻找最大和最小数组元素的函数。换句话说,mid是数组的最大和最小元素之和除以2后四舍五入。
    然后,数组被分割成左右两部分。左边的数组包含所有小于或等于mid的元素,右边的数组包含所有大于mid的元素。左边和右边的元素保持它们在数组中的相对顺序。
    在第三步中,我们选择我们想保留的左和右数组中的哪一个。所选择的数组将取代当前的数组,而另一个数组则被永久地丢弃了。
    你需要帮助Mike找出q prettiness测试的结果。

    请注意,你测试的是数组a的漂亮程度,所以每次漂亮程度测试都是从原始(初始)数组a开始的,因此,第一个切片(如果需要)总是在数组a上进行。

    输入
    每个测试包含一个或多个测试案例。第一行包含测试用例的数量t(1≤t≤100)。

    每个测试用例的第一行包含两个整数n和q(1≤n,q≤105)--数组a的长度和prettiness测试的总数量。

    每个测试用例的第二行包含n个整数a1,a2,...,an(1≤ai≤106)--数组a的内容。

    每个测试用例的下一个q行包含一个整数si(1≤si≤109)--迈克想在第i个测试中得到的元素之和。

    保证n和q的总和不超过105(∑n,∑q≤105)。

    输出
    打印q行,每行都包含一个 "是",如果相应的漂亮度测试通过,则是 "否"。

    例子
    inputCopy
    2
    5 5
    1 2 3 4 5
    1
    8
    9
    12
    6
    5 5
    3 1 3 1 3
    1
    2
    3
    9
    11
    输出拷贝




    是的

    是的



    注释
    第一个测试案例的解释。

    我们可以通过以下方式得到一个和为s1=1的数组。
    1.1 a=[1,2,3,4,5], mid=1+52=3, left=[1,2,3], right=[4,5] 。我们选择保留左边的数组。

    1.2 a=[1,2,3], mid=1+32=2, left=[1,2], right=[3]. 我们选择保留左边的数组。

    1.3 a=[1,2], mid=1+22=1, left=[1], right=[2]. 我们选择保留左边的数组,其总和等于1。

    可以证明,和为s2=8的数组是不可能产生的。
    一个和为s3=9的数组可以通过以下方式生成。
    3.1 a=[1,2,3,4,5], mid=1+52=3, left=[1,2,3], right=[4,5] 。我们选择保留右边的数组,其和等于9。

    可以证明,和为s4=12的数组是不可能产生的。
    我们可以通过以下方式得到一个总和为s5=6的数组。
    5.1 a=[1,2,3,4,5], mid=1+52=3, left=[1,2,3], right=[4,5] 。我们选择保留左边的,其总和等于6。

    对第二个测试案例的解释。

    可以证明一个和为s1=1的数组是不可能产生的。
    我们可以通过以下方式得到一个和为s2=2的数组。
    2.1 a=[3,1,3,1,3], mid=1+32=2, left=[1,1], right=[3,3,3] 。我们选择保留左边的数组,其和等于2。

    可以证明,一个总和为s3=3的数组是不可能产生的。
    我们可以通过以下方式得到一个总和为s4=9的数组。
    4.1 a=[3,1,3,1,3], mid=1+32=2, left=[1,1], right=[3,3,3] 。我们选择保留右边的数组,其和等于9。

    我们可以通过零切分操作得到一个总和为s5=11的数组,因为数组总和等于11。

    题解:

    我们可以发现每次都是根据数组区间最大值+最小值/2,进行分割,与顺序无关,那我们先排序,求一下前缀和以便,求出某段区间的值,

    我们发现通过上述分割操作,找到的值是一定的,并且也不多,

    利用BFS遍历所有区间,每次二分得到比mid大的下标,根据前缀和来得到所求区间的值

    我们可以提前预处理出来所有的值,然后看询问的值是否出现过

    注意我们是可以不切片的,所以所有值相加的值也要存起来

    1. #include<iostream>
    2. #include<algorithm>
    3. #include<cstring>
    4. #include<string>
    5. #include<map>
    6. #include<vector>
    7. #include<queue>
    8. using namespace std;
    9. #define int long long
    10. int n,q,f;
    11. int a[200505];
    12. int b[200050];
    13. map<int,int> vis;
    14. void bfs()
    15. {
    16. queue<pair<int,int>> q;
    17. q.push({1,n});
    18. while(q.size())
    19. {
    20. auto t = q.front();
    21. q.pop();
    22. int l = t.first,r = t.second;
    23. int mid = (a[l] + a[r])/2;
    24. int k = upper_bound(a+1,a+1+n,mid) - a;
    25. int ans ;
    26. if(r >= k)
    27. {
    28. ans = b[r] - b[k-1];
    29. vis[ans] = 1;
    30. q.push({k,r});
    31. }
    32. if(k<=r&&k-1>=l)
    33. {
    34. ans = b[k-1] - b[l-1];
    35. vis[ans] = 1;
    36. q.push({l,k-1});
    37. }
    38. }
    39. }
    40. //1 1 3 3 3
    41. void solve()
    42. {
    43. cin >> n >> q;
    44. for(int i = 1;i <= n;i++)
    45. cin >> a[i];
    46. vis.clear();
    47. sort(a+1,a+1+n);
    48. for(int i = 1;i <= n;i++)
    49. {
    50. b [i] = b[i-1] + a[i];
    51. }
    52. bfs();
    53. vis[b[n]] = 1;
    54. while(q--)
    55. {
    56. int s;
    57. cin >> s;
    58. if(vis[s])
    59. {
    60. cout<<"YES\n";
    61. }
    62. else
    63. {
    64. cout<<"NO\n";
    65. }
    66. }
    67. }
    68. signed main()
    69. {
    70. int t = 1;
    71. cin >> t;
    72. while(t--)
    73. {
    74. solve();
    75. }
    76. }

     

  • 相关阅读:
    还在为日期计算烦恼?Java8帮你轻松搞定
    java计算机毕业设计音乐网站MyBatis+系统+LW文档+源码+调试部署
    短视频矩阵系统软件源码
    直流电机双闭环调速Simulink仿真
    java源码系列:LinkedList的底层实现原理和特性
    Restriction (mathematics)
    pseudorandom-function oracle-Diffie-Hellman (PRF-ODH) assumption
    C++,没有与这些操作数匹配的“[]“运算符
    ASM之ClassWriter
    Spring MVC @Controller和@RequestMapping注解
  • 原文地址:https://blog.csdn.net/m0_64158084/article/details/127986709