zoukankan      html  css  js  c++  java
  • 【u207】最小值

    Time Limit: 1 second
    Memory Limit: 128 MB

    【问题描述】

    N个数排成一排,你可以任意选择连续的若干个数,算出它们的和。问该如何选择才能使得和的绝对值最小。
    如:N=8时,8个数如下:
    1 2 3 4 5 6 7 8
    -20 90 -30 -20 80 -70 -60 125
    如果我们选择1到4这4个数,和为20,还可以选择6到8这3个数,和为-5,|-5|=5,该方案获得的和的绝对值最小。


    【输入格式】

    第一行输入N,表示数字的个数。接下来N行描述这N个数字。

    【输出格式】

    第一行输出一个整数,表示最小绝对值的和,第二行包含两个整数表示形成该绝对值和最长序列的长度。

    【数据规模】

    40%的数据 N<=4000 对于许多数据,最长序列的长度唯一。 100%的数据 N<=100000,|每个数字的值|<=10^10

    Sample Input1

    20
    12
    -220
    -195
    -316
    -300
    668
    576
    1034
    1055
    972
    -1023
    866
    -1469
    492
    857
    1954
    1685
    1046
    -1748
    -1480
    
    
    

    Sample Output1

    12
    1

    【题解】

    对于区间的静态查询。要用前缀和的方法。

    sum[i]=sum[i-1]+data[i];

    然后处理出sum[0..n]注意要把sum[0]也处理出来。

    然后把这n+1个sum从小到大或从大到小排序。排序完之后。可以保证序列最小和

    就是min{abs(sum[i]-sum[i-1])}其中i∈(1..10);

    因为排序之后相邻的sum值是最接近的。

    然后要记录sum对应的i。

    最大sum相同时。就让他们的差的绝对值最大就好。

    如果全是正数则不用排序。因为sum会越来越大。。这样。

    用__int64之后oj才让过了。。

    【代码】

    #include <cstdio>
    #include <algorithm>
    
    using namespace std;
    
    struct node //pos用于记录是哪一个位置的前缀和。
    {
    	__int64 what;
    	int pos;
    };
    
    int n,maxl;
    __int64 x, minn;
    node sum[100001]; //用于存储前缀和。
    
    void input_data()
    {
    	scanf("%d", &n);
    	sum[0].what = 0; //前0个元素的和也要加进去。
    	sum[0].pos = 0; //不然没法单独取到第一个元素。
    	for (int i = 1; i <= n; i++) //输入n个数字记录前缀和
    	{
    		scanf("%I64d", &x); //这是__int64的输入格式。
    		sum[i].what = sum[i - 1].what + x;
    		sum[i].pos = i;
    	}
    }
    
    int cmp(const node &a, const node &b) //sort函数的对比函数
    {
    	if (a.what < b.what) 
    		return 1;
    	return 0;
    }
    
    int abs(int x) //返回x的绝对值。
    {
    	return x < 0 ? -x : x;
    }
    
    void get_ans()
    {
    	minn = sum[1].what; //一开始先处理最小值是第一个。
    	if (minn < 0)
    		minn = -minn;
    	maxl = sum[1].pos; //记录下他的长度。
    	for (int i = 2; i <= n; i++) //枚举每两个前缀和的差的绝对值
    	{
    		__int64 temp = sum[i].what - sum[i - 1].what;
    		int temp2 = abs(sum[i].pos - sum[i - 1].pos);
    		if (temp < minn) //尝试更新最小值。
    		{
    			minn = temp;
    			maxl = temp2;
    		}
    		else //如果相同则看是否长度更长
    			if (temp == minn && temp2 > maxl)
    				maxl = temp2;
    	}
    }
    
    void output_ans()
    {
    	printf("%I64d
    ", minn);
    	printf("%d", maxl);
    }
    
    int main()
    {
    	//freopen("F:\rush.txt", "r", stdin);
    	//freopen("F:\rush_out.txt", "w", stdout);
    	input_data();
    	sort(sum + 0, sum + 1+n, cmp);//要对sum[0..n]都进行排序。
    	get_ans();
    	output_ans();
    	//fclose(stdin);
    	//fclose(stdout);
    	return 0;
    }


  • 相关阅读:
    中台之交付
    mysql之事务
    中台之中台的设计
    0318 guava并发工具
    0312 java接口测试三棱军刺rest-assured
    0309 软件基本原理1
    0308 软件系统的非功能需求
    PELT(Per-Entity Load Tracking)
    CPU亲和度
    硬件相关知识随手笔记
  • 原文地址:https://www.cnblogs.com/AWCXV/p/7632326.html
Copyright © 2011-2022 走看看