首页 > 其他分享 >NOI2023春季测试游记

NOI2023春季测试游记

时间:2023-03-05 13:11:53浏览次数:54  
标签:dist int text 春季 NOI2023 mode 区间 1005 游记

这还要写游记?

直接进入题解环节。

[[春季测试 2023] 涂色游戏]

难度: \(Easy+\)

标签:无

十分弱智的一道题......

显然地,对于任意一个格子 \((x,y)\) ,它最多被两次操作影响它 最终 的状态——对于行 \(x\) 的操作和对于列 \(y\) 的操作。

因为一次操作会被下一次操作覆盖,所以对于每个格子 \((x,y)\) 只需要看对于行 \(x\) 的操作和对于列 \(y\) 的操作的时间戳哪个大就行了。

简单地说,若对于行 \(x\) 的最后一次操作为将它染成 \(c_i\) ,对于列 \(y\) 的最后一次操作为将它染成 \(c_j\) ,那么若 \(i<j\) ,则格子 \((x,y)\) 的颜色为 \(c_j\) ;否则为 \(c_i\) 。

注意没被染色的格子为 \(0\) ,时间复杂度为 $ \Theta(nm+q) $ 。

点击查看代码
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int T,n,m,q;
pair<int,int> row[100005],line[100005];
inline void solve()
{
	memset(row,0,sizeof(row)),memset(line,0,sizeof(line));
	scanf("%d%d%d",&n,&m,&q);
	for(int i=1;i<=q;++i)
	{
		int opt,pos,color; scanf("%d%d%d",&opt,&pos,&color);
		if(opt==0) row[pos]=make_pair(color,i);
		if(opt==1) line[pos]=make_pair(color,i);
	}
	for(int i=1;i<=n;++i)
	{
		for(int j=1;j<=m;++j)
		{
			if(row[i]==make_pair(0,0)&&line[j]==make_pair(0,0)) printf("0 ");
			else printf("%d ",(row[i].second>line[j].second)?(row[i].first):(line[j].first));
		}
		putchar('\n');
	}
}
int main()
{
	scanf("%d",&T);
	while(T--) solve();
	return 0;
}

[[春季测试 2023] 幂次]

难度: \(Normal\)

标签:暴力

如果你的暴力没过,那么就说明你的暴力不够优雅。

[[春季测试 2023] 圣诞树]

难度: \(Hard-\)

标签:区间类型动态规划、贪心算法

2023.3.4,傻逼待宵因没认真看样例痛失80pts,警钟长鸣。

很多人写的都是完全贪心,这当然是错误的,但是正解还是包含一些贪心思想的。

我们以 \(k\) 为分割点,将凸包分为两段:左段和右段。例如在题目给的图中,整个凸包就被分为了 $ \{ 1,2,3,4 \} $ 和 $ \{ 5,6,7,8,9 \} $ 两段,其中 $ \{ 1,2,3,4 \} $ 为左段, $ \{ 5,6,7,8,9 \} $ 为右段。

因为测试数据是顺序给出的,所以每一段的顺序还是原来的顺序。根据贪心思想,对于左段来说,设这里面有两个点 \(i,j(i<j)\) ,那么就不能先到 \(j\) 点再回到 \(i\) 点;对于右段来说,设这里面有两个点 \(i,j(i<j)\) ,那么就不能先到 \(i\) 点再回到 \(j\) 点。

所以其实我们都是已经走过了一个包含 \(k\) 的区间 \([l,r]\) ,然后再走到下一个点的。这不就是区间DP典题 关路灯 吗?

我们设 \(f(l,r,0)\) 表示已经走完了 \([l,r]\) 这段区间且走到这个区间的左端点 \(l\) 的最小花费,设 \(f(l,r,1)\) 表示已经走完了 \([l,r]\) 这段区间且走到这个区间的右端点 \(r\) 的最小花费,那么对于 \(f(l,r,0)\) ,我们肯定是先走完了 \([l+1,r]\) 这段区间再转移到 \(l\) 的,所以是从 \(f(l+1,r,0/1)\) 这个状态转移的。如果我们在 \([l+1,r]\) 这个区间的左端点 \((l+1)\) 上,那么就要花费 $ \text{dist} (l+1,l)$ 走到 \(l\) ;如果在右端点 \(r\) ,那么就要花费 $ \text{dist} (r,l)$ 走到 \(l\) ,所以有转移方程:

\[f(l,r,0)= \min \{ f(l+1,r,0)+ \text{dist} (l+1,l),f(l+1,r,1)+ \text{dist} (r,l) \} \]

对于 \(f(l,r,1)\) 的转移同理,我们要先走完区间 \([l,r-1]\) 才能走到 \(r\) :

\[f(l,r,1)= \min \{ f(l,r-1,0)+ \text{dist} (l,r),f(l,r-1,1)+ \text{dist} (r-1,r) \} \]

然而还有一个很重要的一点: 因为终点不一定是 \(1\) 或 \(n\) ,所以我们走的实际上是一个环 。既然是环,那么我们就要断环为链,具体方法如下:

  • 设二元组序列 \((x',y')_i\)

  • 令 \((x',y')_{i-k}=(x,y)_i (i \in [k+1,n])\)

  • 令 \((x',y')_{n-k+i}=(x,y)_i (i \in [1,k-1])\)

  • 令 \((x',y')_n=(x,y)_k\)

  • 以 \(n\) 为起点, \((x',y')\) 为各点位置进行区间DP

简单地说,就是将右段放在前面,左段放在右段的后面, \(k\) 放在最后。

最后输出路径即可。时间复杂度为 $ \Theta(n^2) $ 。

点击查看代码
#include <cmath>
#include <cstdio>
#include <algorithm>
#define x first
#define y second
using namespace std;
const double inf=1e18;
int n,k,id[1005];
double dis[1005][1005],f[1005][1005][2],pre[1005][1005][2];
pair<double,double> a[1005],b[1005];
inline double dist(const int A,const int B) {return sqrt((b[A].x-b[B].x)*(b[A].x-b[B].x)+(b[A].y-b[B].y)*(b[A].y-b[B].y));}
inline void print()
{
	int l=1,r=n-1,mode=(f[1][n-1][0]+dist(1,n)>f[1][n-1][1]+dist(n-1,n));
	printf("%d ",k);
	while(true)
	{
		printf("%d ",id[(mode==0)?(l):(r)]);
		if(l==r) return;
		l+=(mode^1),r-=mode,mode=pre[l-(mode^1)][r+mode][mode];
	}
}
int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;++i) scanf("%lf%lf",&a[i].x,&a[i].y);
	for(int i=n;i>=1;--i)
		if(!k||a[i].y>a[k].y) k=i;
	for(int i=k+1;i<=n;++i) b[i-k]=a[i],id[i-k]=i;
	for(int i=1;i<k;++i) b[n-k+i]=a[i],id[n-k+i]=i;
	b[n]=a[k];
	for(int len=2;len<n;++len)
		for(int l=1,r=l+len-1;r<n;++l,++r)
		{
			f[l][r][0]=f[l][r][1]=inf;
			if(f[l][r][0]>f[l+1][r][0]+dist(l+1,l)) f[l][r][0]=f[l+1][r][0]+dist(l+1,l),pre[l][r][0]=0;
			if(f[l][r][0]>f[l+1][r][1]+dist(r,l)) f[l][r][0]=f[l+1][r][1]+dist(r,l),pre[l][r][0]=1;
			if(f[l][r][1]>f[l][r-1][0]+dist(l,r)) f[l][r][1]=f[l][r-1][0]+dist(l,r),pre[l][r][1]=0;
			if(f[l][r][1]>f[l][r-1][1]+dist(r-1,r)) f[l][r][1]=f[l][r-1][1]+dist(r-1,r),pre[l][r][1]=1;
		}
	return print(),0;
}

标签:dist,int,text,春季,NOI2023,mode,区间,1005,游记
From: https://www.cnblogs.com/for-moon/p/17180283.html

相关文章

  • THUPC2023 游记
    回首曾经在THU打的三场比赛,仿佛是很久以前的事情了。如今的我可能是仍不愿走出舒适区,可能是畏惧曾经的OI水平已退化为“自然语言翻译器”或者“经典套路识别器”,可能......
  • NOI2023春测游记
    DAY-?教练跟我们说让我们参加下春季赛,被迫参加(本来自己就太菜了)迫不得已就去秦皇岛吧DAY-1这天一直在做DP,感觉脑子快炸了不过DP感觉好多了DAY0准备出发了(打了打......
  • NOI 2023 春季测试 游记
    开坑,待填。upd:寄了,不想填,但还是来填坑了。\(Day-1\)看板子,什么都不会。(悲)\(Day0\)睡了一天觉,晚上和学长们玩了各种游戏/se。\(Day1\)早上起来感觉隐隐约约肚......
  • 春季测试 2023 幂次
    **F出原题\(3\lek\)时,\(a\le10^6\)可以暴力统计答案,对于重复的贡献可以用类似筛法的东西去维护,因为每个数只会被筛一次,所以是\(O(n)\)的,但是统计答案要带一个常数。......
  • 2023/3/4 NOI春季测试游记
    高中第一次参加正式比赛……挺紧张的,不过在家附近的连大比又没那么紧张其实(再说19年也比过)……Day-114514知道了NOIP要延期,感觉我这种小萌新也能去见识见识大场面了,......
  • 2023 NOI春季测试游记
    坐标:HE背景:因NOIP取消,所以变成了春季赛。\(Day\;0\)中午坐火车去火车站,坐了三个小时的车到了考点,路上是真的一点没卷……晚上到酒店,教练还请我们吃自助餐,虽然但是......
  • 2023.3.4 NOI春季赛游记
    2023.3.3Day-1本来想着去机房试试小黑屋的Linux顺便敲点板子然后正好因为腿疼拿到了体活课的假条就直接体活+自习+晚自习一起翘掉去机房了晚上6点他们去吃饭我下楼......
  • NOI2023 春季测试游寄
    \(\mathtt{20221126}\)记:\(\text{noip}\)今天比赛,陕西取消,准备明年三月的春季测试(\(\text{noip}\)替代品)。\(\mathtt{20230218}\):https://www.noi.cn/xw/2022-12-14/......
  • noi春季赛2023游记
    赛场看到题,无力吐槽T1模拟就完了,写了1.5h,居然还有提醒“道路千万条,清零第一条。多测不清空,爆零两行泪”这种提醒,给我看傻了T2好像可以用容斥,不过我把完全平方数单算,再把......
  • 下册开学期末+CSP-J游记
    下册开学期末+CSP-J游记Day-14期末Day-7今天家长会,老师公布成绩/fn/fn/fn。政治和历史考废了,然后其他都挺好。语文\(101\),数学\(120\),英语\(86+29.17\),历史\(8......