首页 > 其他分享 >2024牛客暑期多校训练营3

2024牛客暑期多校训练营3

时间:2024-07-23 20:17:38浏览次数:17  
标签:std CI now int 多校 2024 牛客 include define

Preface

又被隔壁干烂了,这场最抽象的是三个人开局被 A 卡的死去活来,一直到中期的时候才以 WA 三发的代价过了这个题

封榜后徐神狠狠发力连过两题,使得最后勉强只被打出 \(n+1\) 而不是 \(n+2\),鉴定为我是纯纯的飞舞


Bridging the Gap 2

首先不难发现过程一定是先进行 \(T=\rceil\frac{n-R}{R-L}\lceil\) 次来回操作,每次带 \(R\) 个人过去,再带 \(L\) 个人回来;最后一轮直接带 \(R\) 个人过去

考虑将每个人的体力分为两部分,一部分为将自己运过去需要的;另一部分是多余的可以帮着运送别人的,显然后者就是 \(\lfloor\frac{h_i}{2}\rfloor\)

但由于多出的体力超出 \(T\) 的部分没有意义,因此我们求出 \(\sum_{i=1}^n \min(T,\lfloor\frac{h_i}{2}\rfloor)\),将这个值于 \(T\times L\) 做比较即可

#include <bits/stdc++.h>
#define int long long
using namespace std;

signed main(void) {
    std::ios::sync_with_stdio(false); cin.tie(0);
    int n, l, r;
    std::cin >> n >> l >> r;
    std::vector<int> h(n);
    for(auto &h: h) std::cin >> h, h = (h - 1) >> 1;
    
    std::sort(h.begin(), h.end());
    int res = n - r;
    
    int tot = (n - r + (r - l) - 1) / (r - l);
    int sum = 0;
    for (int i=0; i<n; ++i){
        sum += min(tot, h[i]);
    }
    if (sum >= tot*l) cout << "YES\n";
    else cout << "NO\n";
    
    return 0;
}


Crash Test

手玩一下会发现这个撞击的过程很像求 \(\gcd\),因此不难发现最后等价于用一个 \(\gcd(a_1,a_2,\dots,a_n)\) 的东西去撞墙

#include<bits/stdc++.h>
using namespace std;
#define int long long

const int INF = (int)1e18+5;

int n, D,x,g  ;
signed main(){
    ios::sync_with_stdio(0); cin.tie(0);
    cin>>n>>D; int g=0;
    for (int i=1;i<=n;++i) cin>>x,g=__gcd(g,x);
    return printf("%lld",min(D%g,g-D%g)),0;
}

Delete 4 edges

不可做题,弃疗


Dominoes!

很有意思的构造题

首先要注意如果每个块的两个数都不相同,则我们存在一种很 trivial 的构造方案

即先随便放一个骨牌,然后接下来每次放的时候如果按照原顺序不会造成冲突就直接放,否则翻转当前骨牌一定可以放下

现在就考虑存在同色骨牌时怎么操作,手玩一下会发现可以贪心地把出现次数多的同色骨牌和其它同色骨牌合并,每次取出出现次数最多的两种一起放置即可

注意当存在一种同色骨牌出现次数很多时,就需要用其它的异色骨牌填到它们中间,如果找不到这样的骨牌就无解了

否则可以将原问题转化为只有异色骨牌的问题,就很容易处理了

#include<cstdio>
#include<iostream>
#include<utility>
#include<queue>
#include<vector>
#include<map>
#define RI register int
#define CI const int&
#define fi first
#define se second
using namespace std;
typedef pair <int,int> pi;
const int N=200005;
int n,x[N],y[N],used[N]; vector <pi> ans; map <int,int> rst;
int main()
{
    RI i; priority_queue <pi> hp;
    for (scanf("%d",&n),i=1;i<=n;++i)
    {
        scanf("%d%d",&x[i],&y[i]);
        if (x[i]==y[i]) ++rst[x[i]],used[i]=1;
    }
    for (auto [val,cnt]:rst) hp.push(pi(cnt,val));
    while (hp.size()>=2)
    {
        auto [mxc,mxv]=hp.top(); hp.pop();
        auto [smxc,smxv]=hp.top(); hp.pop();
        ans.push_back(pi(mxv,mxv));
        ans.push_back(pi(smxv,smxv));
        if (mxc-1>0) hp.push(pi(mxc-1,mxv));
        if (smxc-1>0) hp.push(pi(smxc-1,smxv));
    }
    if (hp.size()==1)
    {
        auto [cnt,val]=hp.top();
        if (ans.empty()||val!=ans.back().se)
        ans.push_back(pi(val,val)),--cnt;
        vector <int> vec; for (i=1;i<=n;++i)
        if (!used[i]&&val!=x[i]&&val!=y[i]) vec.push_back(i);
        if ((int)vec.size()<cnt) return puts("No"),0;
        for (i=1;i<=cnt;++i)
        {
            int id=vec.back(); vec.pop_back(); used[id]=1;
            ans.push_back(pi(x[id],y[id]));
            ans.push_back(pi(val,val));
        }
    }
    for (i=1;i<=n;++i) if (!used[i])
    {
        if (!ans.empty()&&ans.back().se==x[i]) swap(x[i],y[i]);
        ans.push_back(pi(x[i],y[i]));
    }
    puts("Yes");
    for (auto [x,y]:ans) printf("%d %d\n",x,y);
    return 0;
}

Malfunctioning Typewriter

首先可以将所有串建出一个 Trie 树,并统计出每个子树内终止节点的数量

假设当前处于根节点,左子树有 \(x\) 个终止节点,右子树有 \(y\) 个终止节点

由于最后匹配的过程一定会在这个点选择 \(x+y\) 次,因此不妨把贡献拆开单独考虑,计算出每个点选择的总贡献然后相乘即可

而最优的选择策略可以用 DP 预处理出来,总复杂度 \(O(nm)\)

#include <bits/stdc++.h>

using real = double;

real dp[1001][1001];

int go[1'000'001][2], O = 1, siz[1'000'001];

int main() {
    std::ios::sync_with_stdio(false);
    int n, m;
    real p;
    std::cin >> n >> m >> p;
    dp[0][0] = 1;
    for(int i = 1; i <= 1000; ++i) dp[0][i] = dp[i][0] = dp[i - 1][0] * p;
    
    for(int i = 1; i <= 1000; ++i) for(int j = 1; j <= 1000; ++j) {
        dp[i][j] = std::max(
            p * dp[i - 1][j] + (1. - p) * dp[i][j - 1],
            (1. - p) * dp[i - 1][j] + p * dp[i][j - 1]
        );
    }
    
    while(n--) {
        std::string s; std::cin >> s;
        int cur = 1;
        for(auto c: s) {
            int u = c - '0';
            if(!go[cur][u]) go[cur][u] = ++O;
            siz[cur = go[cur][u]] += 1;
        }
    }
    
    real ans = 1;
    for(int i = 1; i <= O; ++i) ans *= dp[siz[go[i][0]]][siz[go[i][1]]];
    
    std::cout << std::fixed << std::setprecision(15);
    std::cout << ans << char(10);
    return 0;
}


MMR Double Down Tokens

神秘计数题,弃疗


Pythagorathean Transformation

神秘数论题,弃疗


Rectangle Intersection

前面我和祁神出了一堆假做法,后面还得靠徐神看一眼秒了

考虑把一个矩形拆成四个边界,对于每个格点,考虑维护出其上/左/下/右四个方向上距离最近的边界,这个实现时可以用扫描线+一阶差分处理

最后遍历每个格子,计算其对应的四个边界对答案的贡献,样例给了个很强的 Corner Case,就是必须对覆盖了至少一次的格子计算答案,否则会把贡献算小

总复杂度 \(O(nm+k)\)

#include <bits/stdc++.h>

constexpr int $n = 2002;

int n, m, k;
int S[$n][$n];
int U[$n][$n], D[$n][$n], L[$n][$n], R[$n][$n];
int u[$n][$n], d[$n][$n], l[$n][$n], r[$n][$n];

int main(void) {
    std::ios::sync_with_stdio(false);
    std::cin >> n >> m >> k;
    
    for(int i = 0, x1, y1, x2, y2; i < k; ++i) {
        std::cin >> x1 >> y1 >> x2 >> y2;
        S[x1][y1] += 1;
        S[x2 + 1][y1] -= 1;
        S[x1][y2 + 1] -= 1;
        S[x2 + 1][y2 + 1] += 1;
        U[x1][y1] += 1, U[x1][y2 + 1] -= 1;
        D[x2][y1] += 1, D[x2][y2 + 1] -= 1;
        L[x1][y1] += 1, L[x2 + 1][y1] -= 1;
        R[x1][y2] += 1, R[x2 + 1][y2] -= 1;
    }
    
    for(int i = 1; i <= n; ++i) for(int j = 1; j <= m; ++j)
        U[i][j] += U[i][j - 1],
        D[i][j] += D[i][j - 1],
        L[i][j] += L[i - 1][j],
        R[i][j] += R[i - 1][j],
        S[i][j] += S[i - 1][j] + S[i][j - 1] - S[i - 1][j - 1];
    
    memset(u, -1, sizeof(u));
    for(int i = 1; i <= n; ++i) for(int j = 1; j <= m; ++j) {
        if(U[i][j]) u[i][j] = i;
        else        u[i][j] = u[i - 1][j];
    }
    memset(d, -1, sizeof(d));
    for(int i = n; i >= 1; --i) for(int j = 1; j <= m; ++j) {
        if(D[i][j]) d[i][j] = i;
        else        d[i][j] = d[i + 1][j];
    }
    memset(l, -1, sizeof(l));
    for(int j = 1; j <= m; ++j) for(int i = 1; i <= n; ++i) {
        if(L[i][j]) l[i][j] = j;
        else        l[i][j] = l[i][j - 1];
    }
    memset(r, -1, sizeof(r));
    for(int j = m; j >= 1; --j) for(int i = 1; i <= n; ++i) {
        if(R[i][j]) r[i][j] = j;
        else        r[i][j] = r[i][j + 1];
    }
    int ans = n * m;
    for(int i = 1; i <= n; ++i) for(int j = 1; j <= m; ++j) {
        if(S[i][j] == 0) continue;
        if(u[i][j] < 0) continue;
        if(d[i][j] < 0) continue;
        if(l[i][j] < 0) continue;
        if(r[i][j] < 0) continue;
        ans = std::min(ans, (d[i][j] - u[i][j] + 1) * (r[i][j] - l[i][j] + 1));
    }
    std::cout << ans << char(10);
    return 0;
}

Removing Elements

又是个神秘题,弃疗


Rigged Games

很经典的题,首先可以用 two pointers 快速求出从每个位置出发下次会到串中的哪个位置,并且这一句获胜方是谁

根据这个初始条件直接倍增预处理,询问时找到使得大局不结束的最靠后的位置即可

#include<cstdio>
#include<iostream>
#include<utility>
#define RI register int
#define CI const int&
using namespace std;
typedef pair <int,int> pi;
const int N=100005;
struct ifo
{
    int x,y;
    inline ifo(CI X=0,CI Y=0)
    {
        x=X; y=Y;
    }
    friend inline ifo operator + (const ifo& A,const ifo& B)
    {
        return ifo(A.x+B.x,A.y+B.y);
    }
    inline int Max(void)
    {
        return max(x,y);
    }
}w[N][20]; int n,a,b,to[N][20]; char s[N];
int main()
{
    RI i,j; scanf("%d%d%d%s",&n,&a,&b,s);
    int c[2]={0,0}; ++c[s[0]-'0'];
    for (i=j=0;i<n;++i)
    {
        while (max(c[0],c[1])<a) ++c[s[j=(j+1)%n]-'0'];
        to[i][0]=(j+1)%n; w[i][0]=c[0]==a?ifo(0,1):ifo(1,0);
        --c[s[i]-'0'];
    }
    //for (i=0;i<n;++i) printf("i=%d, to=%d, win=(%d,%d)\n",i,to[i][0],w[i][0].x,w[i][0].y);
    for (j=1;j<20;++j) for (i=0;i<n;++i)
    {
        to[i][j]=to[to[i][j-1]][j-1];
        w[i][j]=w[i][j-1]+w[to[i][j-1]][j-1];
    }
    for (i=0;i<n;++i)
    {
        int pos=i; ifo cur;
        for (j=19;j>=0;--j)
        if ((cur+w[pos][j]).Max()<b)
        cur=cur+w[pos][j],pos=to[pos][j];
        cur=cur+w[pos][0];
        putchar(cur.x==b?'1':'0');
    }
    return 0;
}

Slay the Spire: Game Design

唉,塔批;唉,网络流

要求每条路径上都有至少一个怪的情况就是经典的删点使得图不连通,跑个最小割即可

这题要求有 \(k\) 个怪就是把每个点复制 \(k\) 层再跑类似的过程,具体建图方式可以看官方题解

#include<cstdio>
#include<iostream>
#include<cstring>
#include<queue>
#define RI register int
#define CI const int&
using namespace std;
typedef long long LL;
const int N=1005,INF=1e9;
int n,m,k,x,y,in[N],out[N]; vector <int> v[N];
inline int ID(CI d,CI v,CI tp)
{
	return (d-1)*(2*n)+tp*n+v;
}
namespace Network_Flow
{
	const int NN=10005,MM=NN*20;
	struct edge
	{
		int to,nxt,v;
	}e[MM<<1]; int cnt=1,head[NN],cur[NN],dep[NN],clk[NN],s,t; queue <int> q;
    inline void addedge(CI x,CI y,CI z)
    {
        e[++cnt]=(edge){y,head[x],z}; head[x]=cnt;
        e[++cnt]=(edge){x,head[y],0}; head[y]=cnt;
    }
    #define to e[i].to
    inline bool BFS(void)
    {
        memset(dep,0,(t+1)*sizeof(int)); dep[s]=1; q=queue <int>(); q.push(s);
        while (!q.empty())
        {
            int now=q.front(); q.pop();
			for (RI i=head[now];i;i=e[i].nxt)
            if (e[i].v&&!dep[to]) dep[to]=dep[now]+1,q.push(to);
        }
        return dep[t];
    }
    inline int DFS(CI now,CI tar,int dis)
    {
        if (now==tar) return dis; int ret=0;
        for (RI& i=cur[now];i&&dis;i=e[i].nxt)
        if (e[i].v&&dep[to]==dep[now]+1)
        {
            int dist=DFS(to,tar,min(dis,e[i].v));
            if (!dist) dep[to]=INF;
            dis-=dist; ret+=dist; e[i].v-=dist; e[i^1].v+=dist;
            if (!dis) return ret;
        }
        if (!ret) dep[now]=0; return ret;
    }
    inline void DFS1(CI now)
    {
    	clk[now]=1; for (RI i=head[now];i;i=e[i].nxt) if (e[i].v&&!clk[to]) DFS1(to);
    }
    inline void DFS2(CI now)
    {
    	clk[now]=2; for (RI i=head[now];i;i=e[i].nxt) if (e[i].v&&!clk[to]) DFS2(to);
    }
    #undef to
    inline LL Dinic(LL ret=0)
    {
        while (BFS()) memcpy(cur,head,(t+1)*sizeof(int)),ret+=DFS(s,t,INF); return ret;
    }
};
using namespace Network_Flow;
int main()
{
	RI i,j; scanf("%d%d%d",&n,&m,&k);
	for (i=1;i<=m;++i)
	{
		scanf("%d%d",&x,&y);
		++out[x]; ++in[y]; v[x].push_back(y);
	}
	for (i=1;i<=n;++i)
	{
		for (auto to:v[i])
		{
			if (!in[i]&&!out[to]) return puts("-1"),0;
			if (!in[i]) addedge(i,ID(1,to,0),INF); else
			if (!out[to]) addedge(ID(k,i,1),to+n,INF); else
			{
				for (j=1;j<=k;++j) addedge(ID(j,i,1),ID(j,to,0),INF);
			}
		}
	}
	s=ID(k,n,1)+1; t=s+1;
	for (i=1;i<=n;++i)
	{
		if (!in[i]) addedge(s,i,INF);
		if (!out[i]) addedge(i+n,t,INF);
		if (in[i]&&out[i])
		{
			for (j=1;j<=k;++j) addedge(ID(j,i,0),ID(j,i,1),1);
			for (j=1;j+1<=k;++j) addedge(ID(j,i,0),ID(j+1,i,1),INF);
		}
	}
	LL res=Dinic();
	if (res>=INF) return puts("-1"),0;
	printf("%lld\n",res); DFS1(s); DFS2(t);
	for (i=1;i<=n;++i) if (in[i]&&out[i])
	{
		bool flag=0;
		for (j=1;j<=k;++j)
		{
			if (clk[ID(j,i,0)]==1&&clk[ID(j,i,1)]==2) { flag=1; break; }
		}
		if (flag) printf("%d ",i);
	}
	return 0;
}

Sudoku and Minesweeper

签到题,我题意都不知道

#include<bits/stdc++.h>

int main() {
    std::string s[9];
    int x, y;
    for(int i = 0; i < 9; ++i) std::cin >> s[i];
    for(int i = 3; i < 6; ++i) for(int j = 3; j < 6; ++j) if(s[i][j] == '8') {
        x = i, y = j;
    }
    for(int i = 0; i < 9; ++i) {
        for(int j = 0; j < 9; ++j) if(i == x && j == y)
            std::cout << '8';
        else std::cout << '*';
        std::cout << char(10);
    }
    return 0;
}

Postscript

唉现在每天都菜的发昏,后期经典等死就完了,什么时候能担起逆转大局的角色呢

标签:std,CI,now,int,多校,2024,牛客,include,define
From: https://www.cnblogs.com/cjjsb/p/18319552

相关文章

  • xfs-2024-NOIP模拟赛
    0722模拟赛这是计数专场吗,把我秒掉了。难原:P7050[NWRRC2015]Concatenation给定两个字符串a,b,从a中选一段前缀,b中选一段后缀(前后缀都可以为空),并将选出的后缀拼在选出的前缀后面。你需要求出有多少种本质不同的串(可以为空)。思路总方案数减去不合法的方案数。以ab......
  • 2024.7.23 Linux——DNS服务搭建(day12)
    (一)搭建nginx1.首先布置基本环境要求能够ping通外网,有yum源2.安装nginxyum-yinstallnginx然后查看验证 3.修改网页配置文件修改文件,任意编写内容,然后去物理机测试(二)创建一台客户端1.模拟一下客户,用母机克隆一台作为我们的客户端然后只需修改地址,保证能够ping......
  • 【专题】2024AI人工智能体验营销行业研究报告合集PDF分享(附原数据表)
    原文链接:https://tecdat.cn/?p=37084原文出处:拓端数据部落公众号 随着体验经济与智能新时代的双重浪潮席卷而来,既有的传统营销框架与初始体验营销理念逐渐显露出对快速膨胀的数字化生态及企业多元化需求的适应性不足。在此背景下,构建一个契合数智化时代脉搏的全新营销理论体系......
  • 2024獬豸杯WP
    2024獬豸杯总体比较轻松?基本可以一把梭?手机取证1、IOS手机备份包是什么时候开始备份的。(标准格式:2024-01-20.12:12:12)看logs,只有时间,日期看文件修改日期。2024-01-15.14:19:442、请分析,该手机共下载了几款即时通讯工具。(标准格式:阿拉伯数字)33、手机机主的号码得ICCID是......
  • DASCTF 2024 暑季赛 cry部分
    1z_RSA观察题目,我们看到给与我们的乘值的高位和pq高位相同,此处我们可以利用进行爆破:foriinrange(200):PQ=pq+ix=factor(PQ)print(i,x)iflen(x)==2andint(x[1][0]).bit_length()<=130:print(x)break爆破后我们即可求得准......
  • React 18【实用教程】(2024最新版)
    搭建开发环境含@配置,react-developer-tools和ReduxDevTools下载安装https://blog.csdn.net/weixin_41192489/article/details/138523829JSX语法https://blog.csdn.net/weixin_41192489/article/details/138649165组件父子组件传值、兄弟组件传值、越层组件......
  • 【学术会议征稿】第八届控制工程与先进算法国际论坛(IWCEAA 2024)
    第八届控制工程与先进算法国际论坛 8th International Workshopon ControlEngineering and AdvancedAlgorithms(IWCEAA 2024)第八届控制工程与先进算法国际论坛(IWCEAA 2024)将于2024年11月1-3日在中国南京隆重举行。会议旨在为从事算法、控制工程与计算机技术研究......
  • 2024-7-23 信友队模考总结
    开考题目难度应该是升序的,开T1发现看着不简单,就有点突突。T2看起来比较简单,想到了双指针,但是方向不对,搞了20min出不来就回去看T1。开写T1想出来就很好写了,想到两个点就可以组成一条边从而确定一个正方形(当然没有对角线),直接\(\mathcal{O}(n^2)\)暴力枚举判断就可以了,......
  • 2024年华为OD机试真题-执行时长-C++-OD统一考试(C卷D卷)
    2024年OD统一考试(D卷)完整题库:华为OD机试2024年最新题库(Python、JAVA、C++合集) 题目描述:为了充分发挥GPU算力,需要尽可能多的将任务交给GPU执行,现在有一个任务数组,数组元素表示在这1秒内新增的任务个数且每秒都有新增任务,假设GPU最多一次执行n个任务,一次执行耗时1秒,在保证GPU......
  • 【经济金融EI会议】【四大高校支持】第四届互联网金融与数字经济国际学术会议(ICIFDE 2
    【四大高校支持】第四届互联网金融与数字经济国际学术会议(ICIFDE2024)The4thInternationalConferenceonInternetFinanceandDigitalEconomy会议官网:www.icifde.org会议时间:2024年8月16日-18日会议地点:中国-黑龙江-哈尔滨(线上会议)提交检索:EI,Scopus,CNKI,GoogleS......