首页 > 其他分享 >区间问题----差分+离散化+前缀和

区间问题----差分+离散化+前缀和

时间:2022-10-22 19:24:00浏览次数:47  
标签:dist 前缀 int mid 差分 ---- numbers ans include

 

《二维离散化+二维前缀和+二维双指针算法+二分+以点代二维区间》

思路:

  首先,利用二分,将求解问题变成判断问题,二分边长

  关于在二维平面上的任意区域的数值问题可以用预处理二维前缀和解决

  然后因为利用二分出来的边长,我们枚举在二维平面上的两个点,然后在通过前缀和算出这个区域上的草的数量,如果满足条件,return true;

 但是如果这里不离散化是做不了的,因为按照,枚举x与y要1e8时间复杂度,

但是这里N很小,x与y最多也只会出现1000次

1000*1000=1e6复杂度可以接受

 1 #include <iostream>
 2 #include <cstring>
 3 #include <vector>
 4 #include <algorithm>
 5 using namespace std;
 6 typedef pair<int, int> PII;
 7 const int N = 1010;
 8 int c, n;
 9 PII points[N];
10 vector<int> numbers;
11 int sum[N][N];
12 int get(int x)
13 {
14     int l = 1, r = numbers.size() - 1, ans = -1;
15     while (l <= r)
16     {
17         int mid = (l + r) >> 1;
18         if (numbers[mid] >= x)
19         {
20             ans = mid;
21             r = mid - 1;
22         }
23         else
24             l = mid + 1;
25     }
26     return ans;
27 }
28 bool check(int len)
29 {
    //可以发现我这里双指针,我只枚举了x2,y2的值,而x1与y1我并没有枚举,而是受了x2与y2的限制而移动 30 for (int x1 = 1, x2 = 1; x2 < numbers.size(); x2++) 31 { 32 while (numbers[x2] - numbers[x1] + 1 > len) 33 x1++; 34 for (int y1 = 1, y2 = 1; y2 < numbers.size(); y2++) 35 { 36 while (numbers[y2] - numbers[y1] + 1 > len) 37 y1++; 38 if (sum[x2][y2] - sum[x1 - 1][y2] - sum[x2][y1 - 1] + sum[x1 - 1][y1 - 1] >= c) 39 return true; 40 } 41 } 42 return false; 43 } 44 int main() 45 { 46 cin >> c >> n; 47 for (int i = 1; i <= n; i++) 48 { 49 int x, y; 50 scanf("%d%d", &x, &y); 51 points[i] = {x, y}; 52 numbers.push_back(x), numbers.push_back(y); 53 } 54 numbers.push_back(0); 55 sort(numbers.begin(), numbers.end()); 56 numbers.erase(unique(numbers.begin(), numbers.end()), numbers.end()); 57 58 /* for (int i = 0; i < numbers.size(); i++) 59 cout << numbers[i] << " "; 60 cout << endl; */ 61 62 for (int i = 1; i <= n; i++) 63 { 64 int x = get(points[i].first), y = get(points[i].second); 65 /* cout << "pos:" << x << " " << y << endl; */ 66 sum[x][y]++; 67 } 68 for (int i = 1; i < numbers.size(); i++) 69 for (int j = 1; j < numbers.size(); j++) 70 sum[i][j] += sum[i - 1][j] + sum[i][j - 1] - sum[i - 1][j - 1]; 71 int l = 1, r = 10000, ans = -1; 72 while (l <= r) 73 { 74 int mid = (l + r) >> 1; 75 if (check(mid)) 76 { 77 ans = mid; 78 r = mid - 1; 79 } 80 else 81 l = mid + 1; 82 } 83 cout << ans; 84 return 0; 85 }

《一维差分+一维以点代区间问题》

 

 思路:这道题是明显的离散化+差分,但是这里有个坑点:一维以点代区间

像这样的要定义好点的含义,否则会影响求前缀和与差分的规则

 

 1 #include <iostream>
 2 #include <algorithm>
 3 #include <cstring>
 4 #include <vector>
 5 using namespace std;
 6 typedef pair<int, int> PII;
 7 const int N = 2 * 1e5 + 5, INF = 1e9 + 10;
 8 int pre[N], n, sum[N];
 9 vector<int> dist;
10 PII arr[N];
11 int get(int x)
12 {
13     int l = 0, r = dist.size() - 1, ans;
14     while (l <= r)
15     {
16         int mid = (l + r) >> 1;
17         if (dist[mid] >= x)
18         {
19             ans = mid;
20             r = mid - 1;
21         }
22         else
23             l = mid + 1;
24     }
25     return ans;
26 }
27 int main()
28 {
29     cin >> n;
30     int pos = 0, nowpos;
31     dist.push_back(0);
32     dist.push_back(INF);
33     dist.push_back(-INF);
34     for (int i = 1; i <= n; i++)
35     {
36         int num;
37         char c[2];
38         scanf("%d", &num);
39         scanf("%s", c);
40         if (c[0] == 'R')
41         {
42 
43             nowpos = pos + num;
44             arr[i] = {pos, nowpos};
45             /*   cout << pos << " " << nowpos << endl; */
46         }
47         else if (c[0] == 'L')
48         {
49 
50             nowpos = pos - num;
51             arr[i] = {nowpos, pos};
52             /*  cout << nowpos << " " << pos << endl; */
53         }
54         pos = nowpos;
55         dist.push_back(nowpos);
56     }
57     sort(dist.begin(), dist.end());
58     dist.erase(unique(dist.begin(), dist.end()), dist.end());
59     /*  for (int i = 0; i <= dist.size() - 1; i++)
60          cout << dist[i] << " ";
61      cout << endl; */
62     for (int i = 1; i <= n; i++)
63     {
64         int l = get(arr[i].first), r = get(arr[i].second);
65         /* cout << l << " " << r << endl; */
66         pre[l] += 1, pre[r] -= 1;
67     }
68     for (int i = 1; i <= dist.size() - 1; i++)
69         sum[i] = sum[i - 1] + pre[i];
70     int ans = 0;
71     for (int i = 1; i < dist.size() - 1; i++)
72     {
73         if (sum[i] >= 2)
74             ans += dist[i + 1] - dist[i];
75     }
76     cout << ans;
77     return 0;
78 }

 《逆向思维的差分》

 这道题要我们找出温度,但是我们不如逆向考虑一下,

对于每一头牛,给定区间[l,r];我们不如首先来一个温度轴

每一头牛,在温度[0,l-1]上产奶x,[r+1,INF]上产奶z,【l,r】上产奶y,然后可以将这些值加入到温度轴上

在全部牛枚举完后,扫一遍温度轴上的数值,然后最大值对应的温度即为答案

但是温度轴有0-1e9,但是牛有20000比较小,说明温度值出现的全部值不超过40000,用离散化

 1 #include <iostream>
 2 #include <cstring>
 3 #include <algorithm>
 4 #include <vector>
 5 using namespace std;
 6 const int N = 4 * 1e4 + 5;
 7 int n, x, y, z;
 8 vector<int> temp;
 9 pair<int, int> cows[N];
10 int pre[N];
11 int get(int x)
12 {
13     int l = 0, r = temp.size() - 1, ans = -1;
14     while (l <= r)
15     {
16         int mid = (l + r) >> 1;
17         if (temp[mid] >= x)
18         {
19             ans = mid;
20             r = mid - 1;
21         }
22         else
23             l = mid + 1;
24     }
25     return ans;
26 }
27 int main()
28 {
29     cin >> n >> x >> y >> z;
30     for (int i = 1; i <= n; i++)
31     {
32         int l, r;
33         scanf("%d%d", &l, &r);
34         cows[i] = {l, r};
35         temp.push_back(l), temp.push_back(r);
36     }
37     temp.push_back(-1), temp.push_back(1e9 + 10);
38     sort(temp.begin(), temp.end());
39     temp.erase(unique(temp.begin(), temp.end()), temp.end());
40     for (int i = 1; i <= n; i++)
41     {
42         int l = get(cows[i].first), r = get(cows[i].second);
43         pre[0] += x;
44         pre[l] += y - x;
45         pre[r + 1] += z - y;
46     }
47     int ans = 0, num = 0;
48     for (int i = 0; i <= temp.size() - 1; i++)
49     {
50         num += pre[i];
51         ans = max(ans, num);
52     }
53     cout << ans;
54     return 0;
55 }

 

标签:dist,前缀,int,mid,差分,----,numbers,ans,include
From: https://www.cnblogs.com/cilinmengye/p/16817069.html

相关文章

  • 求球高度
    #include<stdio.h>intmain(){ floath=100; floats=100; h=h/2; inti; for(i=2;i<=10;i++){ s=s+2*h; h=h/2; } printf("%f,%f",......
  • 单例 Bean 的线程安全问题
    最近面试遇到一个问题:单例Bean的线程安全问题怎么解决的。之前了解但是没有深究它的解决方法。大部分时候我们并没有在项目中使用多线程,所以很少有人会关注这个问题。......
  • 周六1900C++班级20221022-for循环
    for语法:for(initialization;test-condition;increment){statement-list;}for构造一个由4部分组成的循环:初始化,可以由0个或更多的由逗号......
  • 计算机组成与设计 硬件软件接口 第五版 RISC-V 电子书 pdf
    作者:[美]JohnL.Hennessy/[美]DavidA.Patterson出版社:机械工业出版社副标题:硬件/软件接口原作名:ComputerOrganizationandDesign:TheHardware/Software......
  • 猴子摘桃
    #include<stdio.h>intmain(){ intx=1; inty=0; intday; for(day=9;day>=1;day--){ y=(x+1)*2; x=y; } printf("%d\n",y); return......
  • 2022.10.22每日一题
    饿饿饭饭题目描述有\(n\)个同学正在排队打饭,第\(i\)个同学排在从前往后第\(i\)个位置。但是这天食堂内只有一个食堂阿姨,为了使同学们都能尽快的吃上饭,每一个同学......
  • 什么是分布式,史上最全详解!​
    转自:https://blog.csdn.net/androidstarjack/article/details/118347050  集群与分布式区别集群:复制模式,每台机器做一样的事。分布式:两台机器分工合作,每台机器做的......
  • dremio 23 s3 插件默认ssl 配置问题
    问题描述如下图  操作一般我们会按照(注意需要开启s3兼容模式),以上问题说明是依赖ssl,但是我们已经声明了不使用ssl  或者endpoint带上http如下,数据桶可......
  • 并发和并行
    并发和并行是多线程中比较重要的两个概念并发一句话总结,微观看是串行的,宏观上看感觉是并行的。在单核cpu中所有的线程之间是并发执行的,cpu执行任务时在多个线程之间连续......
  • 【Python】第3章-18 统计一行文本的单词个数
    随机输入一个字符串,把最左边的10个不重复的英文字母(不区分大小写)挑选出来。如没有10个英文字母,显示信息“notfound”输入格式:在一行中输入字符串输出格式:在一行中......