首页 > 其他分享 >NFLS 训练总结 1(updating)

NFLS 训练总结 1(updating)

时间:2023-08-08 20:57:09浏览次数:33  
标签:总结 10 ch int void NFLS while maxn updating

前言

没有前言。


Day 0

上午听完校际交流最后一节课,下午 2 点出发去 nj。

在车上和两位巨佬先讨论了一些之前的题目。

然后看到 nj 地铁,某位巨佬想要出一个图论题。

一开始是这样的:给一个无向图,一开始你有一定的体力,你可以步行走过一些边,会消耗体力,也可以坐地铁,不消耗体力,但是会花钱。如果你体力不足,可以花钱补充体力,问从一个点到另一个点最少花多少钱。

后来变成了这样:给一个无向图,一开始你有一定的体力,你可以步行走过一些边,会消耗体力,也可以坐地铁,不消耗体力,但是会花钱。有一些关键点,如果你经过关键点,可以花钱补充体力。你有一次“锁血”的机会,可以保证你的体力在某段路径上在某个值不变。问从一个点到另一个点最少花多少钱。

什么拼接题()

然后南外给的胸牌就是一个纸片,上面写了“2023暑期信息竞赛集训”,我甚至不知道该写什么,逆天。

后来看同学的博客,听说是 IOI 赛制,好耶!

虽然还是可能爆 0,但至少不会莫名挂分了。


Day 1

总体情况

1000+1200+1400+1600+1800+1575=8575,rk65

总体来说感觉虽然开题晚一点点但是前面做起来非常顺利,后面可能有一些懈怠了,不想思考导致排名掉了很多。主要是 T6 ,再多想想就可以多拿不少分。

T1

发现可以使用U盘,于是找到了快读板子放到缺省源里面,因此比别人晚开题大概 2min。

开 T1,第一遍没过样例,被吓到了。后来发现排序反了,改了一下,过了。

就是先排序,然后看有多少人可以替换第四名。

然而到最后都没有发现题目已经帮我们排好序了

反正 6 人中仅有 lx 在赛后发现

T2

开 T2,发现比 T1 简单。一个伞直接看为一个 \(2\cdot d+1\) 的区间,用 \(n\) 除以它上取整。写了 2min。一遍过。

T3

开 T3,发现显然 \(d\) 的值为所有要走的距离的最大公约数。写了 3-4min,一遍过。

T4

开 T4,一开始没看数据范围,感觉很难……后来发现 \(n\leq 8\),如果搜索操作 3,最多 5 层,不会超时。但是搜操作 1,2 就可能不行。

然后发现也许操作一二不需要搜索,在合并前加和合并后加等价,所以就把所有操作一二放在三后面。然后打了一个很暴力的 \(O(n!\cdot n^3)\) (大概是这个复杂度,那个 \(O(n^3)\) 是暴力计算操作一二的。

写了 15min,一遍过。

#include<bits/stdc++.h>
using namespace std;
namespace IO{
	template<typename T> inline void write(T x){
		if(x<0) putchar('-'),x=-x;
		if(x==0){
			putchar('0'); return ;
		}
		if(x>9) write(x/10);
		putchar(x%10+'0');
		return ;
	}
	template<typename T> inline void read(T &x){
		x=0; int w=1; char ch=getchar();
		while(!isdigit(ch)){
			if(ch=='-') w=-1; ch=getchar();
		}
		while(isdigit(ch))
			x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
		x*=w; return ;
	}
}
using namespace IO;
#define writesp(x) write(x),putchar(' ')
#define writeln(x) write(x),putchar('\n')
#define inf 0x3f3f3f3f
#define mod 998244353
#define maxn 100010
#define int long long
int n,l[maxn],a,b,c,ans;
bool cmp(int x,int y){return x>y;}
void dfs(int m){
	if(m>=3){
		for(int i=1;i<=n;++i)
			for(int j=1;j<=n;++j)
				for(int k=1;k<=n;++k){
					if(i==j||j==k||i==k) continue;
					if(!l[i]||!l[j]||!l[k]) continue;
					ans=min(ans,abs(l[i]-a)+abs(l[j]-b)+abs(l[k]-c)+10*(n-m));
				}
		if(m==3) return ;
	}
	for(int i=1;i<=n;++i)
		for(int j=i+1;j<=n;++j){
			if(!l[i]||!l[j]) continue;
			int t1=l[i],t2=l[j];
			l[i]=t1+t2; l[j]=0;
			dfs(m-1); l[i]=t1,l[j]=t2;
		}
}
signed main(){
//	freopen(".in","r",stdin);
//	freopen(".out","w",stdout);
//	ios::sync_with_stdio(false);
//	cin.tie(0); cout.tie(0);
	read(n); read(a); read(b); read(c);
	for(int i=1;i<=n;++i) read(l[i]);
	sort(l+1,l+n+1,cmp);
	ans=inf; dfs(n); writeln(ans);
	return 0;
}

T5

开 T5,有一个显然的 \(O(n^6)\) 做法,先写了,+1440。

然后算了一下值域。由于本人算无能,算成了 \(100\times 100 \times 1000=10^8\) ,认为直接开会 MLE。在这里耗时约 30min。

看榜,发现好多人切了 T5,T6还写了很多部分分。

他们怎么都这么强啊.jpg

然后去想 T6 了。

后来想到 map 这种神奇的东西,用了,但是 \(O(n^4\cdot \log n)\) 超时了。

重新计算一遍,发现是 \(10^7\) ,于是果断开数组存可能的值。

然而忘了处理负数,又 WA 了一发,然后使用数组的时候每个数加上一个 \(10^7\) ,过了。(还好是 IOI 赛制

就是枚举两个矩形的交点,分左上右下和左下右上两种情况。

先枚举左上所有值,存到数组里,然后枚举右下所有值,如果和左上重复就加上贡献。

左下右上做法相似。

至于清空,再用加进来的方式把加上的都减掉就行了。

#include<bits/stdc++.h>
using namespace std;
namespace IO{
	template<typename T> inline void write(T x){
		if(x<0) putchar('-'),x=-x;
		if(x==0){
			putchar('0'); return ;
		}
		if(x>9) write(x/10);
		putchar(x%10+'0');
		return ;
	}
	template<typename T> inline void read(T &x){
		x=0; int w=1; char ch=getchar();
		while(!isdigit(ch)){
			if(ch=='-') w=-1; ch=getchar();
		}
		while(isdigit(ch))
			x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
		x*=w; return ;
	}
}
using namespace IO;
#define writesp(x) write(x),putchar(' ')
#define writeln(x) write(x),putchar('\n')
#define inf 0x3f3f3f3f
#define mod 998244353
#define maxn 110
int n,a[maxn][maxn],ans,h[20000010],t;
map<int,int> mp;
int calc(int x1,int yy1,int x2,int y2){
	return a[x2][y2]-a[x1-1][y2]-a[x2][yy1-1]+a[x1-1][yy1-1];
}
signed main(){
//	freopen(".in","r",stdin);
//	freopen(".out","w",stdout);
//	ios::sync_with_stdio(false);
//	cin.tie(0); cout.tie(0);
	read(n); ans=0; t=10000000;
	for(int i=1;i<=n;++i)
		for(int j=1;j<=n;++j) read(a[i][j]);
	for(int i=1;i<=n;++i)
		for(int j=2;j<=n;++j) a[i][j]+=a[i][j-1];
	for(int i=1;i<=n;++i)
		for(int j=2;j<=n;++j) a[j][i]+=a[j-1][i];
	for(int k=1;k<n;++k)
		for(int l=1;l<n;++l){
			for(int i=1;i<=k;++i)
				for(int j=1;j<=l;++j) ++h[calc(i,j,k,l)+t];
			for(int i=k+1;i<=n;++i)
				for(int j=l+1;j<=n;++j) ans+=h[calc(k+1,l+1,i,j)+t];
			for(int i=1;i<=k;++i)
				for(int j=1;j<=l;++j) --h[calc(i,j,k,l)+t];
			for(int i=k+1;i<=n;++i)
				for(int j=1;j<=l;++j) ++h[calc(k+1,j,i,l)+t];
			for(int i=1;i<=k;++i)
				for(int j=l+1;j<=n;++j) ans+=h[calc(i,l+1,k,j)+t];
			for(int i=k+1;i<=n;++i)
				for(int j=1;j<=l;++j) --h[calc(k+1,j,i,l)+t];
		}
	writeln(ans);
	return 0;
}

T6

先打了一个假贪心,每次选票数大于1号的票中的最小值,+1155,很满意于是回去想 T5.

过了 T5 之后回来想 T6,浪费了很多时间之后,发现每次选择并不是一定要选票数比1号多的。于是又打了一个假贪心,+1575,75/100,但是 TLE。

此时还剩不到 10min。

发现第二个假贪心的时间可以写成 \(O(n^2)\) 的,但是没时间写了。后来好像这样写能拿 85。

但是从头到尾都觉得这题正解是 dp。

事实上是贪心。

发现 1 号投谁其实都无所谓,因为首先一号完全领先至少有 2 票,所以剩余的一定至少有一个 0,只要把票投给那个 0 票的人就行了,

枚举最终状态,最终 1 号得到多少票,然后把票数大于一号得票的人,多出的票先去掉,然后再从剩下的中找最小的使1号的票到达枚举的值。

这样计算出的所有答案取 \(\min\)。

#include<bits/stdc++.h>
using namespace std;
namespace IO{
	template<typename T> inline void write(T x){
		if(x<0) putchar('-'),x=-x;
		if(x==0){
			putchar('0'); return ;
		}
		if(x>9) write(x/10);
		putchar(x%10+'0');
		return ;
	}
	template<typename T> inline void read(T &x){
		x=0; int w=1; char ch=getchar();
		while(!isdigit(ch)){
			if(ch=='-') w=-1; ch=getchar();
		}
		while(isdigit(ch))
			x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
		x*=w; return ;
	}
}
using namespace IO;
#define writesp(x) write(x),putchar(' ')
#define writeln(x) write(x),putchar('\n')
#define inf 0x3f3f3f3f
#define mod 998244353
#define maxn 2010
#define int long long
int n,a[maxn],s[maxn],t[maxn],flg,res,ans;
priority_queue<int,vector<int>,greater<int> > q[maxn],pq;
signed main(){
//	freopen(".in","r",stdin);
//	freopen(".out","w",stdout);
//	ios::sync_with_stdio(false);
//	cin.tie(0); cout.tie(0);
	read(n); ans=inf;
	for(int i=2;i<=n;++i) read(a[i]);
	for(int i=2;i<=n;++i) read(s[i]);
	for(int i=n-1;i>=1;--i){
		for(int j=1;j<=n;++j){
			t[j]=0;
			while(q[j].size()) q[j].pop();
		}
		res=0;
		for(int j=2;j<=n;++j) q[a[j]].push(s[j]);
		for(int j=2;j<=n;++j) ++t[a[j]];
		for(int j=2;j<=n;++j){
			while(t[j]>=i){
				--t[j]; ++t[1]; res+=q[j].top(); q[j].pop();
			}
			while(t[j]){
				--t[j]; pq.push(q[j].top()); q[j].pop();
			}
		}
		while(t[1]<i){
			++t[1]; res+=pq.top(); pq.pop();
		}
		ans=min(ans,res);
		while(pq.size()) pq.pop();
	}
	writeln(ans);
	return 0;
}

T7

当时在考场上感觉没什么人过,所以就没写。后来发现有一些部分分是比较好写的。

有没有一种可能,我对链并且只有三种颜色的有思路,但是这两个拆成两个部分分我就不会了。

我怎么这么弱啊.jpg

考虑计算每种颜色贡献,对于每种颜色计算包含它的路径数量。

但是这样还是不太好算。但是发现计算不包含某种颜色的路径数量是好算的。即某一块中不包含这种颜色,大小为 \(sz\),路径数为 \(\frac{sz\times (sz-1)}{2}\)。

然后发现每个点会影响离它最近的祖先,所以 dfs,记录对于每种颜色记录搜到的当前点离他最近的祖先,然后从祖先里面刨去同色点的子树大小,这一团东西里面选起点终点的方案数。

代码实现细节有一点点多,\(dfs\) 稍有些复杂,还有别忘了把上面没有祖先与他同色的点贡献减掉。

#include<bits/stdc++.h>
#define inf 0x3f3f3f3f
#define mod 998244353
#define maxn 200010
#define pb emplace_back
#define int long long
using namespace std;
int T=0,n,m,x,y,c[maxn],sz[maxn],ans,lst[maxn],d[maxn],top[maxn],f[maxn];
vector<int> g[maxn];
void clear(int n){
	m=ans=0;
	memset(sz,0,sizeof(sz));
	memset(lst,0,sizeof(lst));
	memset(top,0,sizeof(top));
	memset(f,0,sizeof(f));
	memset(d,0,sizeof(d));
	for(int i=1;i<=n;++i) g[i].clear();
}
int calc(int x){return x*(x-1)/2;}
void dfs(int x,int fa){
	int tmp=lst[c[x]]; lst[c[x]]=x;
	sz[x]=1; d[x]=0;
	for(int i=0;i<g[x].size();++i){
		int y=g[x][i];
		if(y==fa) continue;
		dfs(y,x); sz[x]+=sz[y];
		ans-=calc(sz[y]-d[x]); d[x]=0;
	}
	lst[c[x]]=tmp;
	if(tmp) d[lst[c[x]]]+=sz[x];
	else top[c[x]]+=sz[x];
}
signed main(){
	ios::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);
	while(cin>>n){
		clear(n); ++T;
		for(int i=1;i<=n;++i){
			cin>>c[i];
			if(!f[c[i]]) ++m,f[c[i]]=1;
		}
		for(int i=1;i<n;++i){
			cin>>x>>y;
			g[x].pb(y); g[y].pb(x);
		}
		ans=calc(n)*m; dfs(1,0);
		for(int i=1;i<=n;++i)
			if(f[c[i]])
				ans-=calc(n-top[c[i]]),f[c[i]]=0;
		cout<<"Case #"<<T<<": "<<ans<<endl;
	}
	return 0;
}

T8

其他

讲课的时候老师讲了一些比较好笑的错误。

比如:在某个循环里面使用 memset 清空一个完整的大数组,还有 #define maxn 100000+5 然后 int a[maxn*2] 这种。

虽然觉得很好笑,但感觉像是我会干出来的事。(不如我的 lca 好笑。

中午在南外转了一圈,机房楼上面有一面墙,墙上是一个树形结构列出了很多算法。有不少是学过了忘了的,还有根本没见过的。

去二楼玩了一些物理实验器材,三楼看了生物标本,回机房休息。本来想写游记,发现中午是不开网的,是能上 OJ。困,下午再订正吧。

下午开网了。订正,但看不到自己提交的代码,并且上午写的我还没保存。晚上回家就看得到了。

OJ 上放了讲评视频,然而我没有耳机,只能看看图,很抽象。

晚上五点放学,本校 7 人调 T7 代码赖到 6 点。

前三题感觉简单,没必要放代码,就没放。


标签:总结,10,ch,int,void,NFLS,while,maxn,updating
From: https://www.cnblogs.com/wonderfish/p/17615339.html

相关文章

  • 8.7总结
    今天相对来说就轻松多了,没有学姐找我,也就定时发一篇推文,原来还在想为啥学长想退部,现在原因明了。今天也没干啥事,在摆乱,不愿意动,发现背上全是那种小疙瘩,去拿药了,说是代谢紊乱,应该是这几天比较焦虑吧......
  • 软件测试|pip常用命令总结
    当使用Python进行开发时,pip是一个非常有用的包管理工具,它可以帮助我们方便地安装、升级和管理Python包。本文将介绍一些常用的pip命令,以帮助您更好地使用pip。查看帮助文档运行pip--help运行这个命令将帮助我们更好地了解pip的使用,pip命令的参数会完整展示出来,如下:pip--helpUsa......
  • 20230808巴蜀暑期集训测试总结
    挂分连挂两天!挂的都是水题!T1两个地方,就三个字符的问题,大小样例居然都没有反映出来,当时想着这道题比较水,之前还去上了个厕所,不能再浪费时间,打完就走了,结果直接挂\(50pts\),比昨天挂的都多。所以,写完就拍!,其实如果前三题都拍了拿\(300\)也比T1挂\(50\)再打个T4\(10pts\)暴......
  • sql注入CTF常见考点方法总结
    SQL注入一、基本注入流程1.判断是否存在注入点(1)?id=xx不同,返回结果不同,则存在注入。(2)数字型判断:​ and1=1正常​ and1=2报错​ 则不存在注入​ 字符型判断:​ 1'and'1'='1正常​ 1'and'1'='2报错​ 则存在注入(3)判断注入点及类型:​ a'......
  • 傻卵错误点总结
    1.傻卵就要认真读题。2.数组别开小。数组别开小。数组别开小。数组别开小。数组别开小。数组别开小。数组别开小。数组别开小。数组别开小。数组别开小。数组别开小。数组别开小。数组别开小。数组别开小。数组别开小。数组别开小。数组别开小。数组别开小。数组别开小。数组别......
  • 代码随想录算法训练营第十三天| 239. 滑动窗口最大值 347.前 K 个高频元素 总结
    239.滑动窗口最大值 (一刷至少需要理解思路)    卡哥建议:之前讲的都是栈的应用,这次该是队列的应用了。本题算比较有难度的,需要自己去构造单调队列,建议先看视频来理解。    题目链接/文章讲解/视频讲解:https://programmercarl.com/0239.%E6%BB%91%E5%8A%A8%E7%AA%......
  • 用python爬虫抓站的一些技巧总结 (转)
    用python爬虫抓站的一些技巧总结zzPython俱乐部您的足迹:»用python爬虫抓站的一些技巧总结zz显示源文件修订记录最近更改索引登录Python俱乐部PythonPythonClub首页Python基础Python常见文件操作Python网络编程Python小技巧Python趣闻Python类小课题我的项目关于本......
  • 上位机_Winform系列总结(winform注入sqlsugar)
    1、引入SqlSugar 2、新建SqlSugarConfig类publicclassSqlSugarConfig{privatestaticreadonlystringconnectionString="DataSource=localhost;Database=h2test;UserId=root;Password=root;charset=utf8;port=3306";publicstaticSq......
  • 2023牛客+杭电补题和总结记录(后半)
    前半继续写要被编辑器卡飞了,换个档杭电第六场\(1002.Pair\Sum\and\Perfect\Square\)对于每个位置可以求出该位置的数和哪些位置的数能够组成完全平方数,因为原序列是排列,并且完全平方数个数不多,所以预处理的复杂度不高。(也可以在后续统计过程中处理)处理出点对以后就变成了......
  • 「赛后总结」暑假 CSP 模拟赛系列 2(8.1~8.3)
    「赛后总结」暑假CSP模拟赛系列2(8.1~8.3)点击查看目录目录「赛后总结」暑假CSP模拟赛系列2(8.1~8.3)20230801(letitdownround)T2神(eldenring)T4动(genshin)20230802(Max_QAQround2)T1随T3AT4C20230803(zero4338round)T2sT3pT4m20230801(letitdownround)蚌。整活大......