标签:NPU numbers 取绝对值 lin start 前缀 index lang ems
一、首先介绍一下什么叫尺取
过程大致分为四步:
1.初始化左右端点,即先找到一个满足条件的序列。
2.在满足条件的基础上不断扩大右端点。
3.如果第二步无法满足条件则到第四步,否则更新结果。
4.扩大左端点,并且回到第二步。
很明显如果要这样做,那么这个序列要是一个有顺序的序列,因为这样的话保证左端点不变,右端点一直向右延伸一定会使答案靠近结果。(可以看一道题理解一下)
Input
Output
Sample Input
5 1 -10 -5 0 5 10 3 10 2 -9 8 -7 6 -5 4 -3 2 -1 0 5 11 15 2 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 15 100 0 0
Sample Output
5 4 4 5 2 8 9 1 1 15 1 15 15 1 15
题意:
这道题是让找一段连续序列,保证找到的这一段序列的(所有数和的绝对值)很靠近那个输入。如果找出来的答案有多个,输出任意一个
题解:
因为这一个输入的n个数的序列不是有序的,是没有办法尺取的(可以想想为什么)
因为我们要找出来一段连续的序列,那么就可以利用前缀和。计算出前缀和之后,对他们排序就可以得到一个有序的序列
这样的话我们保证左端点不变的前提下,右端点向右扩展的话会导致这中间的差值就会越来越大,我们只需要找出来能使右端点减去左端点的值更接近答案的区间就可以(右端点减去左端点的值的几何意义就是左端点在原序列中序号和右端点在原序列中序号之间的和)
代码:
1 #include<stdio.h> 2 #include<string.h> 3 #include<iostream> 4 #include<stdlib.h> 5 #include<algorithm> 6 using namespace std; 7 const int maxn=100005; 8 const int INF=0x3f3f3f3f; 9 struct shudui 10 { 11 int first,second; 12 } p[maxn]; 13 bool cmp(shudui x,shudui y) 14 { 15 return x.first<y.first; 16 } 17 int n,m; 18 void solve(int k) 19 { 20 int l = 0, r = 1, al, ar, av, minn =INF; 21 while (l<=n&&r<=n&&minn!=0) 22 { 23 int temp=p[r].first - p[l].first; 24 if (abs(temp - k) < minn) 25 { 26 minn = abs(temp - k); 27 ar = p[r].second; 28 al = p[l].second; 29 av = temp; 30 } 31 if (temp> k) //当temp>k之后就不用l++,因为之后的答案肯定不如之前的答案更优 32 l++; 33 else if (temp < k) 34 r++; 35 else 36 break; 37 if (r == l) 38 r++; 39 } 40 if(al>ar) 41 swap(al,ar);//因为al和ar大小没有必然关系()取绝对值,所以要交换 42 printf("%d %d %d\n", av, al+1, ar); 43 } 44 int main() 45 { 46 int k; 47 48 while(~scanf("%d%d",&n,&m)) 49 { 50 if (!n&&!m) return 0; 51 p[0].second=p[0].first=0; //这一个初始化要放在里面 52 for (int i = 1; i <= n; i++) 53 { 54 scanf("%d", &p[i].first); 55 p[i].first += p[i - 1].first; 56 p[i].second = i; 57 } 58 sort(p, p + n + 1,cmp); 59 while (m--) 60 { 61 scanf("%d", &k); 62 solve(k); 63 } 64 } 65 return 0; 66 }
标签:NPU numbers 取绝对值 lin start 前缀 index lang ems
原文地址:https://www.cnblogs.com/kongbursi-2292702937/p/11853347.html