Brush title notes - dichotomy

Number range

Given a length in ascending order of an array of integers n, and q queries.
For each query, a return element k start and end positions (position counting from 0).
If the element is not present in the array, "-1-1" is returned.

Input Format

The first row contains an integer n and q, and the array length represents the number of interrogation.
The second line contains n integers (both in the range of 1 to 10,000) indicating the full array.
Next q rows, each row contains an integer k, represents a query element.

Output Format

A total of q rows, each row comprising two integers representing the start and end positions of the elements required.
If the element is not present in the array, "-1-1" is returned.

data range

1≤n≤100000
1≤q≤10000
1≤k≤10000

Ideas:

1. Locate the point left:
- the interval [0,. 1-n-]
- Analyzing conditions: num [mid]> = the tar
2. find the right point:
- the interval [left endpoint,. 1-n-]
- Analyzing conditions: num [mid] <= tar

Code:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 100010;
int n,q;
int num[N];
int main(void)
{
    scanf("%d %d",&n,&q);
    for(int i = 0;i < n;i++)
        scanf("%d",&num[i]);
    while(q--)
    {
        int tar;
        scanf("%d",&tar);
        
        //找左端点
        int l = 0,r = n-1;
        while(l < r)
        {
            int mid = l + r >> 1;
            if(num[mid] >= tar) 
                r = mid;
            else
                l = mid + 1;
        }
        if(num[l] != tar)
            printf("-1 -1\n");
        else
        {
            printf("%d ",l);
            //找右端点
            r = n - 1;
            while(l < r)
            {
                int mid = l + r + 1 >> 1;
                if(num[mid] <= tar)
                    l = mid;
                else
                    r = mid - 1;
            }
            printf("%d\n",l);
        }
    }
	return 0;

}

Robot jumping problem

Robot is playing an old DOS-based games.
The game has N + 1 buildings - numbered from 0 to N, from left to right.
No. 0 building height is 0 units, building height numbered i is H (i) units.
Initially, the construction of the robot in the number zero.
Every step, it jumps to the next (on the right) architecture.
In the k-th assumption that the robot construction, and it is now an energy value E, it will jump to the next step k + 1-th building.
If H (k + 1)> E , then the robot will lose H (k + 1) -E energy value, otherwise it will get the energy value EH (k + 1) of the.
Goal of the game is to reach the N-th building, the energy value in this process can not be negative units.
The question now is how much energy values robot to start the game, you can ensure the successful completion of the game?

Input Format

The first line of the input integer N.
The second line is a space-separated integer N, H (1), H ( 2), ..., H (N) representative of the height of the building.

Output Format

Output an integer value represents an initial minimum unit of energy needed.

data range

\(1≤N,H(i)≤10^5\)
\(1≤N,H(i)≤10^5\)

Ideas:

1. Analyze topic

  • If the amount of energy the robot has all the building height of MAX, then the robot will be able to pass all the building, because the building height less than the energy for the number, the number will increase energy, building height is equal to the number of energy, energy will increase the number 0.
  • And the robot has a number of minimum energy that should be 1, because the minimum height of the building is 1

2. dichotomy

  • Interval [1, max]
  • Analyzing conditions cal (mid)> = 0, i.e., an energy value for a mid, define a function cal (int x) to judge, if left in the building by all energy is greater than 0, indicating that the initial energy value may also continue to shrink.

Code

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;
const int N = 100010;
int n;
int num[N];
int cal(int x,int ma)             
{
    for(int i = 1; i <= n;i++)
    {
        if(x >= num[i])
            x += (x - num[i]);
        else
            x -= (num[i] - x);
        if(x < 0 || x >= ma)     //如果超过max,则一定可以通过;如果小于0,则一定不行
            break;
    }
    return x;
}

int main(void)
{
    scanf("%d",&n);
    int ma = 0;
    for(int i = 1 ;i <= n; i++ )
    {
        scanf("%d", &num[i]);
        ma = max(ma,num[i]);
    }
    //二分法    
    int l  = 1,r = ma;
    while(l < r)
    {
        int mid = (l + r) >> 1;
        if(cal(mid,ma) >= 0) 
            r = mid;
        else
            l = mid + 1;
    }
    printf("%d",r);
    return 0;
    
}

I encountered the pit

Analyzing CAL function () is not in the beginning

if(x < 0 || x >= ma)     
     break;

Data can lead to overflow int x, x range after the really bad accumulating want; I use long long x results overflow. Finally, add the above judgment to think like conditions, neither fast nor overflow.

Points chocolate

Children 's Day kids to have a K-bit Xiaoming house guest. Xiao Ming to come up with a collection of chocolate to entertain the children. Xiaoming a total of N blocks of chocolate, in which the i-th block is a rectangle of Hi x Wi squares thereof.

To be fair, Bob needs to these N K cut out a piece of chocolate chocolate given to children. Cut out chocolate needs met:

  1. Shape is a square with a side length of an integer
  2. The same size

For example a 6x5 chocolate can be cut out of the chocolate or chocolate 6 2x2 3x3 of two.

Of course, the children are hoping to get as large as chocolate, you help small Hi calculate the maximum length of a side is how much it?

Entry

The first line contains two integers N and K. (1 <= N, K < = 100000)
The following N lines contains two integers Hi and Wi. (1 <= Hi, Wi < = 100000)
input to ensure each student at least 1x1 in a chocolate can be obtained.

Export

Output cut out a square of chocolate maximum possible side length.

Thinking

And in front of that question is very similar, and the interval range chocolate size is [1, max], of the side length of chocolate interval for two minutes, if the
determination condition cal (mid)> = k, i.e., may be separated edge length mid chocolate is greater than the k children, then you may be able to put some points more chocolate.

Code

#include <cstring>
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <climits>
using namespace std;
typedef long long LL;
const int N = 100010;
int num[N][2];
int n,k;
LL cal(int dat)
{
    LL sum = 0;
    for(int i = 0; i < n;i++)
    {
        int x = num[i][0]/dat;
        int y = num[i][1]/dat;
        sum +=  x * y;
        if(sum >= k)
            break;
    }
    return sum;
}
int main(void)
{
    scanf("%d %d", &n,&k);
    int ma = 0;               
    for(int i = 0; i < n;i++)
    {
        scanf("%d %d",&num[i][0],&num[i][1]);
        ma = max(ma,min(num[i][0], num[i][1]));//取所有巧克力中宽的最大值
    }
    int l = 1,r = ma;            
    while(l < r)
    {
        int mid = (l + r + 1) >> 1;
        if(cal(mid) >= k)
            l = mid;
        else
            r = mid - 1;
    }
    printf("%d",l);
    return 0;
}

Encountered pit

Initially did not identify the boundary zone, I think it is the right of all the chocolate should be a minimum side length of, because if you want to use every piece of chocolate, then certainly all looking for the minimum side length, but in fact, a number of side length small chocolate can do thing. This was found after submission, or poorly thought.

Four sum of squares

And four square theorem, also known as Lagrange's theorem:
Each positive integer can be represented as a positive integer up to 4 and the square.
0 if included, it can be represented just as the square of the number 4 and.

For example:
5 + 2 = 0 ^ 0 ^ 1 ^ 2 + 2 ^ 2 + 2
7 = 1 ^ 1 ^ 2 + 2 + 1 + 2 ^ 2 ^ 2
(^ symbol indicates the mean power)

For a given positive integer, and there may be multiple square representation.
The number you claim 4 Sort:
0 <= A <= B <= C <= D
and all of the possible representations by a, b, c, d is a primary key in ascending order, the first representation of the final output

Program input is a positive integer N (N <5000000)
claim outputs four non-negative integer, in ascending order, separated by white space

Ideas:

I started to go out into binary think about it, I did not want to come out, a little thought for a moment to enumerate, but the feeling time out to read the solution to a problem, as follows:
1. First calculate the time complexity of enumeration: \ (\ sqrt {5 * 10 ^ 6 = 2240} \)
estimated for the triple loop time complexity is O ( \ (10 ^. 9 \) ), apparently timed out (in fact, because most of the N a, b are small, most of the data will not time out);

2. So to improve enumeration, the general approach is to use space for time . In this problem:

  • C and d can first enumeration, the \ (c ^ 2 + d ^ 2 \) values of c, d stored down (sequential storage, hash)
  • Enumerating a, b, computing \ (n-t = - ^ A ^ 2 B-2 \) , or that the binary hash to determine whether the t has been stored.
  • If t exist, then the direct output.

Method 1 hash

Use \ (c ^ 2 + d ^ 2 \) values directly as a hash function, there may be noted that several methods may constitute a value, but retaining only the first, because the first lexicographically smallest.

#include <cstdio>
#include <cstring>
#include <cmath>
#include <iostream>
#include <algorithm>
using namespace std;

const int N = 5000010;
int num[N][2];
int n;
int main(void)
{
    scanf("%d",&n);
    int m = 0;
    for(int c = 0; c * c <= n;c++ )
        for(int d = c;c * c + d * d <= n;d++)
        {
            int tmp = c*c + d*d;
            if(num[tmp][0] == 0 && num[tmp][1] == 0) //在哈希数组还未赋值的情况下,才允许赋值
            {
                num[tmp][0] = c;
                num[tmp][1] = d;
            }
        }
    for(int a = 0;a * a <= n;a++)
        for(int b = a; a * a + b * b <= n;b++)
        {
            int t = n - a * a - b * b;
            if(t == 0 || (num[t][0] != 0 || num[t][1] != 0))   //判断t是否存在,存在则直接输出a b c d
            {
                printf("%d %d %d %d",a,b,num[t][0],num[t][1]);
                return 0;
            }
        }
    return 0;
}

Method 2-minute
half, then the first step is to save \ (c ^ 2 + d ^ 2 \) value, if repeated, how do keep only dictionary minimum order, this I can think of only traverse, look Gangster program uses I do not know C ++ syntax, stickers, and for learning.

//作者:yxc
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cmath>

using namespace std;

const int N = 2500010;

struct Sum
{
    int s, c, d;
    bool operator< (const Sum &t)const
    {
        if (s != t.s) return s < t.s;
        if (c != t.c) return c < t.c;
        return d < t.d;
    }
}sum[N];

int n, m;

int main()
{
    cin >> n;

    for (int c = 0; c * c <= n; c ++ )
        for (int d = c; c * c + d * d <= n; d ++ )
            sum[m ++ ] = {c * c + d * d, c, d};   //不清楚这里是怎么处理有多种方法可以构成一个值的

    sort(sum, sum + m);

    for (int a = 0; a * a <= n; a ++ )
        for (int b = 0; a * a + b * b <= n; b ++ )
        {
            int t = n - a * a - b * b;
            int l = 0, r = m - 1;
			//二分
            while (l < r)
            {
                int mid = l + r >> 1;
                if (sum[mid].s >= t) r = mid;
                else l = mid + 1;
            }
            if (sum[l].s == t)
            {
                printf("%d %d %d %d\n", a, b, sum[l].c, sum[l].d);
                return 0;
            }
        }

    return 0;
}

Guess you like

Origin www.cnblogs.com/zy200128/p/12594311.html