Educational Codeforces Round 7 题解

时间:2021-05-30 13:50:55

A. Infinite Sequence

Consider the infinite sequence of integers: 1, 1, 2, 1, 2, 3, 1, 2, 3, 4, 1, 2, 3, 4, 5…. The sequence is built in the following way: at first the number 1 is written out, then the numbers from 1 to 2, then the numbers from 1 to 3, then the numbers from 1 to 4 and so on. Note that the sequence contains numbers, not digits. For example number 10 first appears in the sequence in position 55 (the elements are numerated from one).

Find the number on the n-th position of the sequence.

Input

The only line contains integer n (1 ≤ n ≤ 1014) — the position of the number to find.

Note that the given number is too large, so you should use 64-bit integer type to store it. In C++ you can use the long long integer type and in Java you can use long integer type.

Output

Print the element in the n-th position of the sequence (the elements are numerated from one).

Sample test(s)

Input
3
Output
2
Input
5
Output
2
Input
10
Output
4
Input
55
Output
10
Input
56
Output
1


题意
给一个序列1, 1, 2, 1, 2, 3, 1, 2, 3, 4, 1, 2, 3, 4, 5……问序列中第n个数是多少?
思路
把序列分块,第一块1到1;第二块1到2;第三块1到3。。。。。先判断第n个数在哪一块,然后就直接计算出是哪一个数了

#include <bits/stdc++.h>
#define N 100005
#define ll long long
using namespace std;
ll n; 
int main()
{
    ll i;
    ll ans;
    cin >> n;
    i = (ll)sqrt(2*n);
    for (; ; i++)
    {
        if (i*(i+1) ==2*n)
        {
            ans = i;
            break;
        }
        else if (i*(i+1) > 2*n)
        {
            ans = n-i*(i-1)/2;
            break;
        }
    }
    cout << ans;
    return 0;
}

B. The Time

You are given the current time in 24-hour format hh:mm. Find and print the time after a minutes.

Note that you should find only the time after a minutes, see the examples to clarify the problem statement.

You can read more about 24-hour format here https://en.wikipedia.org/wiki/24-hour_clock.

Input

The first line contains the current time in the format hh:mm (0 ≤ hh < 24, 0 ≤ mm < 60). The hours and the minutes are given with two digits (the hours or the minutes less than 10 are given with the leading zeroes).

The second line contains integer a (0 ≤ a ≤ 104) — the number of the minutes passed.

Output

The only line should contain the time after a minutes in the format described in the input. Note that you should print exactly two digits for the hours and the minutes (add leading zeroes to the numbers if needed).

See the examples to check the input/output format.

Sample test(s)

Input
23:59
10
Output
00:09
Input
20:20
121
Output
22:21
Input
10:10
0
Output
10:10


题意
给一个时间,格式是:hh:mm,计算再过a分钟之后的时间是多少
思路
简单水题,直接计算,注意输出格式就行

#include <bits/stdc++.h>
#define ll long long
using namespace std;
int main()
{
    int h, m, hh, mm, t;
    scanf("%d:%d", &h, &m);
    scanf("%d", &t);
    hh = h + (t+m)/60;
    hh %= 24;
    mm = (t+m)%60;
    printf("%02d:%02d", hh, mm);
    return 0;
}

C. Not Equal on a Segment

You are given array a with n integers and m queries. The i-th query is given with three integers li, ri, xi.

For the i-th query find any position pi (li ≤ pi ≤ ri) so that api ≠ xi.

Input

The first line contains two integers n, m (1 ≤ n, m ≤ 2·105) — the number of elements in a and the number of queries.

The second line contains n integers ai (1 ≤ ai ≤ 106) — the elements of the array a.

Each of the next m lines contains three integers li, ri, xi (1 ≤ li ≤ ri ≤ n, 1 ≤ xi ≤ 106) — the parameters of the i-th query.

Output

Print m lines. On the i-th line print integer pi — the position of any number not equal to xi in segment [li, ri] or the value  - 1 if there is no such number.

Sample test(s)

Input
6 4
1 2 1 1 3 5
1 4 1
2 6 2
3 4 1
3 4 2
Output
2
6
-1
4


题意
有一个数组,每次输入l, r, x,输出一个l和r之间的一个不等于x的数的下标
思路
如果直接爆力计算肯定会TLE
我一开始使用线段树,每个结点存放数组中从l到r 的数,然后将每个结点的vector排序一遍,比较时,如果第一个和x不相等就输出第一个数的下标,否则比较最后一个,如果最后一个和x不相等就输出最后一个下标;都相等的话就输出-1。

其实如果用线段树做的话不用那么麻烦,每个结点只要存放数组中从l到r的最小值和最大值就行了,比较的时候也只是比较最大值和最小值

#include <bits/stdc++.h>
#define N 200005
#define ll long long
using namespace std;
struct node
{
    int x, id;
    friend bool operator < (node a, node b)
    {
        return a.x < b.x;
    }
};
typedef vector<node> vn;
vector<vn> v(N<<2);
int a[N], n, m, x;
void PushUp(int r)
{
    int i, l = v[r<<1].size();
    for(i = 0; i < l; i++)
        v[r].push_back(v[r<<1][i]);
    l = v[r<<1|1].size();
    for (i = 0; i < l; i++)
        v[r].push_back(v[r<<1|1][i]);
}
void build(int l, int r, int root)
{
    if (l == r)
    {
        node t;
        scanf("%d", &t.x);
        t.id = l;
        v[root].push_back(t);
        return ;
    }
    int m = (l+r)>>1;
    build(l, m, root<<1);
    build(m+1, r, root<<1|1);
    PushUp(root);
}
int query(int l, int r, int L, int R, int root)
{
    if (l <= L && r >= R)
    {
        int i, l = v[root].size();
        if (v[root][0].x != x)  return v[root][0].id;
        else if (v[root][l-1].x != x)   return v[root][l-1].id;
        else return -1;
    }
    int m = (L+R)>>1, t1 = -1, t2 = -1;
    if (m >= l) t1 = query(l, r, L, m, root<<1);
    if (m < r)  t2 = query(l, r, m+1, R, root<<1|1);
    if (t1 == -1)   return t2;
    if (t2 == -1)   return t1;
    return t1;
}
int main()
{
    int i,j, k, l, r, ans;
    scanf("%d%d", &n, &m);
    build(1, n, 1);
    for (i = 0; i < 3*N; i++)
        sort(v[i].begin(), v[i].end());
    for (i = 0; i < m; i++)
    {
        scanf("%d%d%d", &l, &r, &x);
        ans = query(l, r, 1, n, 1);
        printf("%d\n", ans);
    }
    return 0;
}

其实这道题完全没必要使用线段树,有更为简单的算法
用另一个数组b存放每个数右边第一个和它不相等的数的下标
如果a[l] != x,则输出l,否则输出(b[l]<=r ? b[l]:-1)

另外,在计算b数组的时候还需要注意一下,如果从1到n,一个个的计算的话,还是会TLE的。所有我们计算b数组的时候需要从n到1计算,如果a[i]!=a[i+1]; b[i] = i+1。如果a[i] == a[i+1]; b[i]=b[i+1];

#include <bits/stdc++.h>
#define N 200005
using namespace std;
int a[N], b[N], n, m;
int main()
{
#ifndef ONLINE_JUDGE
    freopen("1.txt", "r", stdin);
#endif
    int i, j, l, r, x;
    scanf("%d%d", &n, &m);
    for (i = 1; i <= n; i++)
        scanf("%d", &a[i]);
    b[n] = n+1;
    for (i = n-1; i > 0; i--)
    {
        if (a[i] != a[i+1]) b[i] = i+1;
        else    b[i] = b[i+1];
    }
    for (i = 0; i < m; i++)
    {
        scanf("%d%d%d", &l ,&r, &x);
        if (a[l] != x)
            printf("%d\n", l);
        else
            printf("%d\n", b[l]<=r ? b[l]:-1);
    }
    return 0;
}

D. Optimal Number Permutation

You have array a that contains all integers from 1 to n twice. You can arbitrary permute any numbers in a.

Let number i be in positions xi, yi (xi < yi) in the permuted array a. Let’s define the value di = yi - xi — the distance between the positions of the number i. Permute the numbers in array a to minimize the value of the sumEducational Codeforces Round 7 题解 .

Input

The only line contains integer n (1 ≤ n ≤ 5·105).

Output

Print 2n integers — the permuted array a that minimizes the value of the sum s.

Sample test(s)

Input
2
Output
1 1 2 2
Input
1
Output
1 1


题意
有一个长度为2*n的数组,数组由1到n,n个数,组成。其中每个数出现两次
对于每个i,i出现的位置是xi, yi (xi < yi) ,其中di = yi - xi
Educational Codeforces Round 7 题解 最小时的数组序列
思路
最小值是0。因为我们只要保证每个数都相距n-i就行了,这样求和结果就是0。于是我们分奇数偶数进行构造,分别占n的长度,对于n特殊处理一下。因为i=n的时候一定是(n-i)=0,所以n放在哪都无所谓

#include <bits/stdc++.h>
#define N 1000005
#define ll long long
using namespace std;
int a[N];
int main()
{
    int n, i, j, l, r, k;
    scanf("%d", &n);
    l = 1;
    r = n;
    k = 1;
    while(l < r)
    {
        a[l] = a[r] = k;
        k += 2;
        l++;
        r--;
    }
    l = n+2;
    r = n<<1;
    k = 2;
    while(l < r)
    {
        a[l] = a[r] = k;
        k += 2;
        l++;
        r--;
    }
    a[n+1] = n;
    if (n&1)    a[n/2+1] = n;
    else    a[(3*n)/2+1] = n;
    n <<= 1;
    for (i = 1; i < n; i++)
        printf("%d ", a[i]);
    printf("%d", a[i]);
    return 0;
}

E. Ants in Leaves

Tree is a connected graph without cycles. A leaf of a tree is any vertex connected with exactly one other vertex.

You are given a tree with n vertices and a root in the vertex 1. There is an ant in each leaf of the tree. In one second some ants can simultaneously go to the parent vertex from the vertex they were in. No two ants can be in the same vertex simultaneously except for the root of the tree.

Find the minimal time required for all ants to be in the root of the tree. Note that at start the ants are only in the leaves of the tree.

Input

The first line contains integer n (2 ≤ n ≤ 5·105) — the number of vertices in the tree.

Each of the next n - 1 lines contains two integers xi, yi (1 ≤ xi, yi ≤ n) — the ends of the i-th edge. It is guaranteed that you are given the correct undirected tree.

Output

Print the only integer t — the minimal time required for all ants to be in the root of the tree.

Sample test(s)

Input
12
1 2
1 3
1 4
2 5
2 6
3 7
3 8
3 9
8 10
8 11
8 12
Output
6
Input
2
2 1
Output
1


题意
有一颗树,树的每个叶子上都有一个蚂蚁,蚂蚁往树根处爬。其中每个结点(根节点除外)最多只能出现一只蚂蚁。问最少经过多长时间全部的蚂蚁才能都到达根节点
思路
由于只有根节点可以同时有多只蚂蚁,so 我们先将根节点的子节点拆除。这样就将一棵树转化为森林,显然森林的其中的一颗耗时最长的树就是最后的答案。
所以我们的问题就是如何计算每棵树最长的耗时。
对于其中的一棵树, 先dfs处理出所有结点的深度,然后对深度排序, 然后计算每个叶子结点到达根结点的时间。 假设第i个蚂蚁到达根结点的时间等于a[i],那么显然a[i] = max(a[i-1]+1, d[i]),等于上一个蚂蚁的时间+1和它所在深度的最大值。

#include <bits/stdc++.h>
#define N 500005
using namespace std;
vector<vector<int> > G(N);
int n;
void dfs(int u, int father, int depth, vector<int> &d)
{
    if (G[u].size() == 1)
    {
        d.push_back(depth);
        return ;
    }
    vector<int>::iterator it;
    int v;
    for (it = G[u].begin(); it != G[u].end(); it++)
    {
        if (*it != father)
            dfs(*it, u, depth+1, d);
    }
}
int main()
{
    int i, j, k, ans = 0, u, v, l;
    vector<int>::iterator it;

    scanf("%d", &n);
    for (i = 1; i < n; i++)
    {
        scanf("%d%d", &u, &v);
        G[u].push_back(v);
        G[v].push_back(u);
    }
    for (it = G[1].begin(); it != G[1].end(); it++)
    {
        vector<int> d;
        dfs(*it, 1, 1, d);
        sort(d.begin(), d.end());
        l = d.size();
        for (i = 1; i < l; i++) 
            d[i] = max(d[i], d[i-1]+1);
        ans = max(ans, d[l-1]);
    }
    printf("%d", ans);
}

F. The Sum of the k-th Powers

There are well-known formulas: Educational Codeforces Round 7 题解,Educational Codeforces Round 7 题解 ,Educational Codeforces Round 7 题解 . Also mathematicians found similar formulas for higher degrees.

Find the value of the sum Educational Codeforces Round 7 题解 modulo 109 + 7 (so you should find the remainder after dividing the answer by the value 109 + 7).

Input

The only line contains two integers n, k (1 ≤ n ≤ 109, 0 ≤ k ≤ 106).

Output

Print the only integer a — the remainder after dividing the value of the sum by the value 109 + 7.

Sample test(s)

Input
4 1
Output
10
Input
4 2
Output
30
Input
4 3
Output
100
Input
4 0
Output
4


题意
计算Educational Codeforces Round 7 题解
思路
听说是用拉格朗日插值公式算的,然而我现在并不知道什么是拉格朗日插公式。。。。。留着以后写吧