Codeforces Round #756 (Div. 3)(D,F)

怎么说呢,只能说太拉胯了,会的不会,不会的不会。

D. Weights Assignment For Tree Edges

链接:
https://codeforces.com/contest/1611/problem/D

题意:
给你两个数组
第一个数组代表第i个结点的父节点是a[i],(能够构成树)
第二个数组代表一个顺序,表示第b[i]个数到父节点的权值和大小排名为i。
输出一个满足这两个条件的数组(第i个数到父节点的权值)。

当时真的是连题目都没有看懂啊,然后看懂题目之后,就看题解了,或许没有自己独立思考的缘故,就在想塔恩的代码怎么实现的

思路:

感觉思路还是听绕的,因为第二个数组代表的是一个大小排名吗,不妨直接按照排名把这个数组置换一下,这样会显得比较容易思考,第一个数组代表他的父节点是哪个而我们需要求得是某结点和他父节点的权值。那么这两个就肯定会有什么联系。我们就可以根据他们排名的差当做他们的边权值不就可以了。

代码:

#include<bits/stdc++.h>
#include<iostream>
#define lll __uint128_t
using namespace std;
inline int read()
{	int num=0,f=1;char ch=getchar();
	while(!isalnum(ch)){if(ch=='-')f=-1;ch=getchar();}
	while(isalnum(ch)){num=num*10+(ch-'0');ch=getchar();}
	return num*f;}
int arr[200010],brr[200010],w[200010];

int main()
{
    int t;
    cin>>t;

    while(t--)
    {
        int n;
        cin>>n;
       for(int i=1;i<=n;i++)
        cin>>arr[i];
       int a;
       for(int i=0;i<n;i++)
        {cin>>a;brr[a]=i;}
        int flag=0;
        for(int i=1;i<=n;i++)
        {w[i]=brr[i]-brr[arr[i]];if(w[i]<0){flag=1;break;} }

        if(flag)cout<<-1;
        else for(int i=1;i<=n;i++)
            cout<<w[i]<<" ";
        cout<<endl;
    }
}

总之还是挺难想到的,想到也不太好解释感觉。也没尝试过按照这个思路想过。也不知道自己能想到还是想不到,其实看到这个数的范围我就感觉就是一个循环的事情(按照这个思路终于F题踩坑了!!!),主要是没读懂题当时。

F. ATM and Students

链接:
https://codeforces.com/contest/1611/problem/F

题意:

给你一个n个数组,还有数s代表初始的钱数。让你在钱大于等于0的前提下找到最长连续字段

了解题意了,在看数值一个e3,一个2e5,让我感觉就是用一个循环,然后我就想什么dp能够完成这个艰巨的任务。然后终于写出来一个代码,把test1过了。然后就停在了test2,最后。。。嗯。。。

等到看代码的时候差点就吐血,二重循环,果断让我想起了,以前做的一个题。那个题,但是那个题我是做出来的,(或许做题真的会固化思维吧)

思路:

按照别人的代码这个题就是一个暴力破解的题,从开始,找两个指针分别指向开头和结尾,然后如果改子段不符合题意就,比较长度,(取最大值)在从开始上一个循环开始的点加1开始,反反复复,最终找到最长子段

代码:

#include<bits/stdc++.h>
using namespace std;
#define rep(i, a, b) for(int i = (a); i <= (b); i++)
#define per(i, a, b) for(int i = (a); i >= (b); i--)
#define ll long long
#define db double
#define VI vector<int>
#define PII pair<int, int>
const db Pi = 3.141592653589793;
const int INF = 0x7fffffff;
const int N = 2e5 + 5;
const db eps = 1e-10;
int cas, n, ansl, ansr, maxn;
ll now, a[N], s;
int main(){
    cin >> cas;
    while(cas--){
        cin >> n >> s;
        rep(i, 1, n) cin >> a[i];
        int t = 1;
        while(s + a[t] < 0) t++;
        ansl = ansr = 0, maxn = 0;
        now = a[t];
        for(int l = t, r = t; l <= n; l++){
            while(r + 1 <= n && s + now + a[r + 1] >= 0) now += a[++r];
            if(s + now >= 0 && maxn < r - l + 1){
                ansr = r, ansl = l;
                maxn = r - l + 1;
            }
            now -= a[l];
        }
        if(maxn <= 0) puts("-1");
        else cout << ansl << " " << ansr << endl;
    }
}

这一个题怎么说呢,非要给他一个合理的解释就是,题目中的这一句话吧It is guaranteed that the sum of the values n over all test cases does not exceed 2⋅105.

总结这一次的比赛吧,整体拉拉夸夸(下一场的div2做的更加的惨目忍睹)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

晨晓翔同学

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值