首页 > 其他分享 >THU训练营预选赛2023

THU训练营预选赛2023

时间:2023-07-16 22:57:51浏览次数:42  
标签:tmp pt int THU 2023 节点 预选赛 include LL

比赛地址

A

Tag: 排列 置换

  • 遍历排列中每个置换环, 找到每个元素需要跳几次才能回到与之相同的元素(最多为环的长度个数)
  • 对每个元素所的次数取max
点击查看代码
// https://tsinghua.contest.codeforces.com/group/sTsHnFxwiH/contest/453495/problem/A
#include <iostream>
#include <algorithm>
#include <vector>
#include <cstring>
#include <map>
using namespace std;
using LL = long long;
using PII = pair<int, int>;
const int N = 5e5 + 10;
int a[N];
int p[N];
bool st[N];
int n;

void solv()
{
    cin >> n;
    for (int i = 1; i <= n; i ++) cin >> a[i];
    for (int i = 1; i <= n; i ++) cin >> p[i];
    int ans = 0;
    for (int i = 1; i <= n; i ++)
        if (!st[i])
        {
            // 遍历包含i的置换环, 并将每个元素对应位置的ai保存到tmp
            vector<int> tmp;
            int pt = i;
            do
            {
                tmp.push_back(a[pt]);
                st[pt] = true;
                pt = p[pt];
                
            } while (!st[pt]);

            map<int, int> mp;  // mp[i] = j, 上次遍历到元素i时的cnt序号为j
            pt = tmp.size() - 1;  // 倒序遍历tmp, 指针从最后一个元素开始
            int cnt = 0;
            mp[tmp[0]] = ++ cnt;  // 倒序遍历tmp, 若循环遍历, 则最后一个元素的上一个元素为第一个元素
            // 第一圈
            while (pt >= 0)
            {
                int x = tmp[pt];
                cnt ++;
                if (mp[x])
                {
                    int t = cnt - mp[x];
                    ans = max(ans, t);
                }
                mp[x] = cnt;
                pt --;
            }
            // 第二圈
            // 因为仅遍历第一圈可能导致某些元素并没有找到与其相同的之前的元素的位置(如第一次访问)
            // 两圈则能保证
            pt = tmp.size() - 1;
            while (pt >= 0)
            {
                int x = tmp[pt];
                cnt ++;
                if (mp[x])
                {
                    int t = cnt - mp[x];
                    ans = max(ans, t);
                }
                mp[x] = cnt;
                pt --;
            }
        }
    cout << ans << endl;
}

int main()
{
    ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    int T = 1;
	// cin >> T;
    while (T --)
    {
        solv();
    }
    return 0;
}

B

Tag: 前缀和 贪心

  • 通过差分计算每个不同观众受到几个评委, 即这个观众的权重
  • 贪心: 按照以上计算的权重, 从大到小, 对观众进行操作减少其 critics;
点击查看代码
// https://tsinghua.contest.codeforces.com/group/sTsHnFxwiH/contest/453495/problem/B
#include <iostream>
#include <algorithm>
#include <vector>
#include <cstring>
using namespace std;
using LL = long long;
using PII = pair<LL, LL>;
const int N = 1e5 + 10;
LL a[N];
LL b[N];


void solv()
{   
    LL n, m, k;
    cin >> n >> m >> k;
    for (int i = 1; i <= n; i ++)
    {
        cin >> a[i];
    }
    for (int i = 1; i <= m; i ++)
    {
        int l, r;
        cin >> l >> r;
        b[l] ++;
        b[r+1] --; 
    }
    vector<PII> tmp;
    LL ans = 0;
    for (int i = 1; i <= n; i ++)
    {
        b[i] += b[i-1];
        tmp.push_back({b[i], a[i]});
        ans += a[i] * b[i];
    } 
    sort(tmp.begin(), tmp.end());
    for (int i = tmp.size() - 1; i >= 0; i --)
    {
        LL x = tmp[i].first, y = tmp[i].second;
        LL c = min(k, y);
        ans -= c * x;
        k -= c;
        if (k == 0) break;
    }
    cout << ans << endl;

}

int main()
{
    ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    int T = 1;
	// cin >> T;
    while (T --)
    {
        solv();
    }
    return 0;
}

D

Tag: 树上差分
总结补充:

  • 树上差分(分为点差分和边, 本题使用点差分), 参考;
  • 最近公共祖先, 参考;
点击查看代码
// https://tsinghua.contest.codeforces.com/group/sTsHnFxwiH/contest/453495/problem/D
/**
 * tag: 树上差分
 */
#include <iostream>
#include <algorithm>
#include <vector>
#include <cstring>
#include <queue>
#include <map>
using namespace std;
using LL = long long;
using PII = pair<LL, LL>;
const int N = 1e5 + 10;
int n;
LL time;
int p[N], t[N], a[N]; // i的父节点, p[i]->t的边权, i的点权
LL depth[N];          // 节点i的深度(按时间边权计算)
int q[N];             // 队列, 存路径
int sup[N];           // 节点i在time时间内, 向上能够到达的最远祖先节点为sup[i]
LL pre[N];            // 树上差分

struct Edge  // 边 u -> v, 边权为 t
{
    int v;
    LL t;
};
vector<Edge> adj[N];  // i的邻接边列表为adj[i]
int ans1;
LL ans2;

// 计算每个节点深度(按边权计算)
void dfs1(int u)
{
    for (auto [v, t] : adj[u])
    {
        depth[v] = depth[u] + t;
        dfs1(v);
    }
}

// 得到sup数组, 即计算 节点i在time时间内, 向上能够到达的最远祖先节点sup[i]
void dfs2(int u, int hh, int tt)
{
    // 将 从节点 sup[i] 到 节点 i 的节点放入队列 q, 通过调整队头指针hh, 找到 sup[i]的位置
    // 这里dfs2中的hh和tt通过局部变量的方式传入, 避免递归返回时破坏队头位置
    q[++tt] = u;
    while (depth[q[tt]] - depth[q[hh]] > time)
        hh++;
    sup[u] = q[hh];
    for (auto [v, t] : adj[u])
        dfs2(v, hh, tt);
}

// 树上差分
// 树上差分公式 :
// 将x-y节点最短路径上的所有节点(含x y)的权值+c, 数组b[i]为差分数组, 则
//      1. b[x] += c
//      2. b[y] += c
//      3. b[a] -= c , a 为 xy 的最近公共祖先
//      4. b[p] -= c , p 为 a 的父节点
// 由于这里的xy节点关系特殊(sup[u]一定是u的祖宗节点, 或等于u), 则 二者的LCA为 sup[u],
// 整理可得dfs3总的两个式子
void dfs3(int u)
{
    pre[p[sup[u]]] -= a[u];
    pre[u] += a[u];
    for (auto [v, t] : adj[u])
        dfs3(v);
}

// 计算树上前缀和, 并维护最大ans
void dfs4(int u)
{
    for (auto [v, t] : adj[u])
    {
        dfs4(v);
        pre[u] += pre[v];
    }

    if (pre[u] > ans2)
    {
        ans2 = pre[u];
        ans1 = u;
    }
}

void solv()
{
    cin >> n >> time;
    for (int i = 2; i <= n; i++)
        cin >> p[i];
    for (int i = 2; i <= n; i++)
    {
        cin >> t[i];
        adj[p[i]].push_back({i, t[i]});
    }
    for (int i = 1; i <= n; i++)
    {
        cin >> a[i];
        a[i]++;
    }
    dfs1(1);
    dfs2(1, 1, 0);
    dfs3(1);
    dfs4(1);
    cout << ans1 << ' ' << ans2 << endl;
}

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int T = 1;
    // cin >> T;
    while (T--)
    {
        solv();
    }
    return 0;
}

标签:tmp,pt,int,THU,2023,节点,预选赛,include,LL
From: https://www.cnblogs.com/o2iginal/p/17558765.html

相关文章

  • 2023-07-16:讲一讲Kafka与RocketMQ中零拷贝技术的运用?
    2023-07-16:讲一讲Kafka与RocketMQ中零拷贝技术的运用?答案2023-07-16:什么是零拷贝?零拷贝(英语:Zero-copy)技术是指计算机执行操作时,CPU不需要先将数据从某处内存复制到另一个特定区域。这种技术通常用于通过网络传输文件时节省CPU周期和内存带宽。➢零拷贝技术可以减少数据......
  • 2023-07-16:讲一讲Kafka与RocketMQ中零拷贝技术的运用?
    2023-07-16:讲一讲Kafka与RocketMQ中零拷贝技术的运用?答案2023-07-16:什么是零拷贝?零拷贝(英语:Zero-copy)技术是指计算机执行操作时,CPU不需要先将数据从某处内存复制到另一个特定区域。这种技术通常用于通过网络传输文件时节省CPU周期和内存带宽。➢零拷贝技术可以减少数据拷贝和......
  • 每日总结2023年7月16日
    今日学习:批处理的学习;java连接池C3P0的连接。遇到的问题:今天在做批处理的时候发现一个问题,就是我的MySQL数据表好像只能存储1000条数据,那么如果数据量远大于此我该如何解决?明天的计划:开启Spring学习。......
  • 萤石网络领跑智能锁行业发展,斩获2023葵花奖五大奖项
    葵花奖作为国内智能家居评选“奥斯卡”,是备受业界关注的重要奖项。在2023年第七届“葵花奖”智能家居评选颁奖盛典上,作为科创板智能家居上市企业的萤石网络斩获多项荣誉,品牌备受关注的智能门锁业务更是夺得五项大奖。萤石网络自2016年开始进军智能门锁行业,多年来不断地对产......
  • python-2023-07-16
    1、easy_install和pip的有什么区别?2、解决requests安装错误的过程中,由于最新设置的pip环境变量放在了最后,想着能不能将pip和python环境变量临近放置,所以将python下移到了pip旁边,导致在cmd输入python就会自动弹出应用商店,后面通过上移python到原来位置才解决掉。3、在python中//......
  • 【动态规划】牛客2023年儿童节比赛 G
    题目链接:https://ac.nowcoder.com/acm/contest/58604/G来源:牛客网设\(f[i]\)表示以\(s[i]\)为结尾的合法序列个数如果\(s[i]\ne1\),那么我们可以在从\(f[i-1]\)到\(f[1]\)所包含的序列后面添加\(s[i]\)构成答案,也可以单独以\(s[i]\)为新的合法序列(也就是后面......
  • 如何在Github挖掘商机
    对于中小企业,初创团队,在github寻找行业相关的项目,是最好的创业途径之一。一方面可以参考借鉴,一方面可以把握行业态势。这其中有两组网址,建议大家经常看看:#1,项目趋势网址:https://github.com/trending最活跃的github项目,默认是按日排名,可以自己按周、月分别看看。#2,项目主题网址:h......
  • 2023.7.16
    1importjava.sql.SQLOutput;2importjava.util.Scanner;3//数组的使用4publicclasstest{5publicstaticvoidmain(String[]args)6{7int[]arrays={1,2,3,4,5};8//for_each循环9for(intarray:arrays){//......
  • 2023年7月16日 天气:晴
       今天早上起来背了10个单词,然后出去打了两个小时的羽毛球,然后看了一小时的电视剧,再就是练了一个小时的字,然后学习了一个小时的java,最后看了一会儿构建之法,编程了一个小时的C语言。  明天打算早上起来看一小时的英语课本,然后出去玩一个小时,再看一小时的java课本,然后练......
  • 暑假训练2023.7.16
    CodeforcesRound882(Div.2)A.TheManwhobecameaGod分成若干段后,分割处的差分会丢失,因此要使所求的各段的差分和最小,只需要让丢失的差分尽可能大。求出序列差分,从大到小排序,去除前\(k-1\)个即可。B.HamonOdyssey首先一个数不断按位与其他数,结果是不增的,因此整个......