HZNU 2019 Summer training 6 -CodeForces - 622

A - Infinite Sequence  CodeForces - 622A 

题目大意:给你一个这样的数列1,1,2,1,2,3,1,2,3,4,1,2,3,4,5.。。。就是从1~n排列(n++).最后问你第n个位置是什么数字。

思路:如果你花点时间列数列的话会发现,1~n的最后一位对应的位置是1~n的和,那我们就大胆使用二分进行搜索这位数。

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
#include<set>
#include<string>
#include<vector>
#include<ctime>
#include<stack>
#include<fstream>
#include<iomanip>
#include<deque>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
#define mm(a,b) memset(a,b,sizeof(a))
#define maxn 300
#define len 150000000+5
#define inf 0x3f3f3f3f
int gcd(int a, int b)
{
    return a % b == 0 ? b : gcd(b, a%b);
}
int main()
{
    ll n;
    scanf("%lld", &n);
    ll l = 1, r = 1e8, mid;
    while (l <= r)
    {
        mid = (l + r) / 2;
        if ((mid + 1)*mid / 2 >= n && (mid - 1)*mid / 2 < n)
            break;
        else if ((mid + 1)*mid / 2 < n)
            l = mid + 1;
        else r = mid - 1;
    }
    ll maxx = (mid + 1)*mid / 2;
    ll ans = mid - (maxx - n);
    printf("%lld\n", ans);
    return 0;
}
View Code

B - Optimal Number Permutation CodeForces - 622D 

题意:给你一个数组,长度为2*n,出现的数字是1~n(每个数字出现两遍)。两个相同数字之间定义了距离di=xi-yi(xi>yi),最后问如何构造这个数组的序列,使得求和.值最小。

思路:看到这样的题先不要着急,想列一下式子,我们就可以发现,你可以构造出一个s=0的数列。

例如:

n=1 1

n=2 1 1 2 2

n=3 1 3 1 2 2 3

n=4 1 2 4 2 1 3 3 4

数字从1~n-1开始排序,n因为怎么样都是0,可以插空排。然后如果这个数字是奇数,我们从左边开始放,偶数从右边开始放。排放就按使得该数(di+i-n)=0的位置排(我也不知道为什么不会覆盖)。然后最后放n。

有个坑点(我自己的),总是数组开小,给你n<=500000,你要开两倍啊。TAT

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
#include<set>
#include<string>
#include<vector>
#include<ctime>
#include<stack>
#include<fstream>
#include<iomanip>
#include<deque>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
#define mm(a,b) memset(a,b,sizeof(a))
#define maxn 2*500000+50
#define len 150000000+5
#define inf 0x3f3f3f3f
int gcd(int a, int b)
{
    return a % b == 0 ? b : gcd(b, a%b);
}
int ans[maxn];
int main()
{
    int n;
    memset(ans, 0, sizeof(ans));
    scanf("%d", &n);
    int left = 1, right = n + 1;
    for (int i = 1; i <= n - 1; i++)
    {
        if (i % 2 == 1)
        {
            ans[left] = i;
            ans[left + n - i] = i;
            left++;
        }
        else
        {
            ans[right] = i;
            ans[right + n - i] = i;
            right++;
        }
    }
    for (int i = 1; i <= 2 * n; i++)
    {
        if (!ans[i]) ans[i] = n;
    }
    for (int i = 1; i <= 2 * n; i++)
    {
        printf("%d ", ans[i]);
    }
    printf("\n");
    return 0;
}
View Code

C - Not Equal on a Segment  CodeForces - 622C 

题意:给你n个数字和m个询问。询问格式:l,r,x,输出在l~r之间a[i]<>x的下标i。

思路:在读入数组的时候就需要将和这个数不相等的位置找到啦,往后面找。因为要么区间的第一个数字和x相等,要么不相等。不相等直接输出当前的位置i,相等就需要往后找啦。

#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<algorithm>
#include<vector>
#include<queue>
#include<functional>
using namespace std;
const int maxn = 2e5 + 50;
int a[maxn], f[maxn];
int main()
{
    int n, m;
    scanf("%d %d", &n, &m);
    for (int i = 1; i <= n; i++)
        scanf("%d", &a[i]);
    for (int i = 1; i <= n; i++)
    {
        if (a[i] != a[i + 1])
            f[i] = i + 1;
        else
        {
            int pos = i;
            for (; a[i] == a[i + 1];) i++;

            for (int j = pos; j <= i; j++)
                f[j] = i + 1;
        }
    }

    while (m--)
    {
        int l, r, x;
        scanf("%d %d %d", &l, &r, &x);
        int flag = 0;
        for (int i = l; i <= r; i++)
        {
            if (a[i] == x)
            {
                if (f[i] > r || f[i] == 0) break;
                printf("%d\n", f[i]);
                flag = 1;
                break;
            }
            else 
            { 
                printf("%d\n", i); 
                flag = 1;
                break; 
            }
        }
        if (!flag) printf("-1\n");
    }
    return 0;
}
View Code

D - Ants in Leaves  CodeForces - 622E 

题意:给你一棵树,一只小蚂蚁在一个叶节点上,他们想回到根节点1,他们可以往自己的父节点爬行,爬行一段花费1个时间点。有个要求是,除了root可以容纳一个ant以外,其它节点只能容纳一只ant,所以如果一个ant在父节点。他的兄弟节点就需要等待一定的时间。问:所有蚂蚁回到叶节点的最小时间是多少?

思路:实验室的巨巨说,可以逆着想,可以假设所有蚂蚁都在根节点上,那么就是所有蚂蚁到叶节点的最短时间。这题就是需要建树,然后dfs一下,给每个子节点深度赋值。

#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<algorithm>
#include<vector>
#include<queue>
#include<functional>
using namespace std;
const int maxn = 5e5 + 50;

int head[maxn * 2], num, cnt, dp[maxn], d[maxn];
struct node
{
    int to, next, w;
}e[maxn*2];

void init()
{
    num = 0;
    memset(head, -1, sizeof(head));
}

void add(int u, int v)
{
    e[num].to = v;
    e[num].next = head[u];
    head[u] = num++;
}

void dfs(int u, int fa, int depth)
{
    int flag = 0;
    for (int i = head[u]; ~i; i = e[i].next)
    {
        int v = e[i].to;
        if (v == fa)
            continue;
        flag = 1;
        dfs(v, u, depth + 1);
    }
    if (!flag)
        d[cnt++] = depth;
}

int main()
{
    init();
    int n, u, v, ans = 0;
    scanf("%d", &n);
    for (int i = 0; i < n - 1; i++)
    {
        scanf("%d %d", &u, &v);
        add(u, v);
        add(v, u);
    }
    for (int i = head[1]; ~i; i = e[i].next)
    {
        int v = e[i].to;
        cnt = 0;
        dfs(v, 1, 1);
        sort(d, d + cnt);
        for (int j = 1; j < cnt; j++)
            d[j] = max(d[j - 1] + 1, d[j]);

        ans = max(ans, d[cnt - 1]);
    }
    printf("%d\n", ans);
    return 0;
}
View Code

E - The Sum of the k-th Powers CodeForces - 622F 

题意:   % 109 + 7

思路:还不会。

猜你喜欢

转载自www.cnblogs.com/Tangent-1231/p/11130306.html