DTOJ 2022-11-21 测试 题解

测试成果

非常寄

35+56+0+8=99

基本上把能犯的错误都犯了

T1 记得 dp 数组初始化 !!!!

T2 记得认真暴搜,不要乱记录访问状态

T3 记得把调试删掉!!!!!

T4 记得开 long long !!

红日学长很会写题目名称,让我看着很想打原神(

可惜挂大分,上次题目名称是 arcaea 的时候也挂大分了

A 风与牧歌的城邦 (mondstadt)

DTOJ P6395

没有温迪的后果就是写不出第一题

题目大意

给定序列 {an},{bn},保证 a1,a2,,an 两两不同。

对于 1lrn,定义区间 [l,r] 的权值如下:设 ap=max{al,al+1,,ar},则 [l,r] 的权值为 bp

你需要将 1n 划分为若干段,求每一段的权值之和的最大值。

对于所有测试数据,保证 1n5×1051ain109bi109,保证 a1,a2,,an1n 的一个排列。

题解

dp 方程不够优()

O(n2) 做法

fi 表示 1i 最大值.

fi=maxprvij<i{fj+w(j+1,i1)}

其中 w(L,R)=bk,maxi[L,R]{ai}=ak

prvi=maxk{ak>ai}

这个不好优化,我们考虑调教式子

变成这样

fi=maxj{fprvi,prvi0maxprvik<i{fk}+bi,prvi0max{0,max1k<i{fk}}+bi,prvi=0

O(nlogn) 做法

单调栈处理 prvi,线段树处理 fi 最大值

代码

#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 5e5+5;
const ll inf = 1e18;
int n,a[N],b[N];
int st[N],tp,prv[N];
ll f[N];
struct Sagiri
{
	int l,r;
	ll mx;
} t[N<<2];
#define ls (p<<1)
#define rs (p<<1)|1
void build(int p, int l, int r)
{
	t[p].l=l,t[p].r=r;
	if(l==r) { t[p].mx=-inf; return ; }
	int mid=(l+r)>>1;
	build(ls,l,mid),build(rs,mid+1,r);
	t[p].mx=max(t[ls].mx,t[rs].mx);
}
void change(int p, int x, ll v)
{
	if(t[p].l==t[p].r) { t[p].mx=v; return ; }
	int mid=(t[p].l+t[p].r)>>1;
	if(x<=mid) change(ls,x,v);
	else change(rs,x,v);
	t[p].mx=max(t[ls].mx,t[rs].mx);
}
ll query(int p, int l, int r)
{
	if(t[p].l==l and t[p].r==r) return t[p].mx;
	int mid=(t[p].l+t[p].r)>>1;
	if(r<=mid) return query(ls,l,r);
	else if(l>mid) return query(rs,l,r);
	else return max(query(ls,l,mid),query(rs,mid+1,r));
}
int main()
{
	scanf("%d",&n);
	for(int i=1; i<=n; i++) scanf("%d",&a[i]);
	for(int i=1; i<=n; i++) scanf("%d",&b[i]);
	for(int i=1; i<=n; i++)
	{
		while(tp and a[st[tp]]<a[i]) tp--;
		if(tp>0) prv[i]=st[tp];
		st[++tp]=i;
	}
	for(int i=1; i<=n; i++) f[i]=-inf;
	build(1,1,n);
	
	for(int i=1; i<=n; i++)
	{
		if(prv[i]) f[i]=f[prv[i]];
		if(i==1) f[i]=b[i];
		else if(prv[i]) f[i]=max(f[i],query(1,prv[i],i-1)+b[i]);
		else f[i]=max(f[i],max(0ll,query(1,1,i-1))+b[i]);
		change(1,i,f[i]);
	}
	printf("%lld\n",f[n]);
	return 0;
}

我只能说我为什么想不出来,甚至暴力写挂,呜呜呜

B 岩与契约的海港 (liyue)

DTOJ P6396

虽然有钟离,可是还是挂分了

题目大意

给定 n 个蛋糕,每块蛋糕有一个美味值 wi。蛋糕的两面分别涂有一种奶油 ai, bi,奶油共有四种类型,分别以 XYZW 表示。

蛋糕 A 能叠放在蛋糕 B 上当且仅当蛋糕 A 底面的奶油与蛋糕 B 顶面的奶油是同一种。其中底面和顶面可以任意指定,即可以对蛋糕进行翻转。

你需要从 n 个蛋糕中选择若干个,并将它们以任意方向、任意顺序叠在一起。求所选蛋糕的美味度之和的最大值。

题解

很好转化成图论模型.

WXYZ 看做四个点,把一个蛋糕看做一条边

我们就是要找一条路径,每一条边只经过一次,边权和的最大值.

注意到如果重边数大于 2,可以在经过它的时候,多走一个来回.

所以最多少走一条边(一定是最小的那条)

于是对于每两个点重边,记录他边数的奇偶,边权和,边权最小值.

现在图中最多 12 条边,轻松暴搜完成.

可惜不知道为什么写挂了,测试完改改就过了,不知道错哪了(

代码

#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 5e5+5;
int n;
int sum[6][6],cnt[6][6],mn[6][6];
int tmp[6][6];
int vt[6];
int st[10],tp;
int dfs(int u, int cur)
{
	if(cur>13) return 0;
	st[++tp]=u;
	int res=0;
	for(int i=1; i<=4; i++) vt[i]=0;
	for(int i=1; i<=tp; i++) vt[st[i]]=1;
	for(int i=1; i<=4; i++) if(vt[i]) res+=sum[i][i];
	for(int i=1; i<=4; i++) for(int j=1; j<=4; j++) tmp[i][j]=0;
	for(int i=1; i<tp; i++)
	{
		int u=st[i],v=st[i+1];
		if(u>v) swap(u,v);
		tmp[u][v]++;
	}
	int flag=0;
	for(int i=1; i<=4; i++)
		for(int j=i+1; j<=4; j++)
		{
			if(tmp[i][j]>=3) flag=1;
			else if(tmp[i][j]==2 and cnt[i][j]<2) flag=1;
			else if(tmp[i][j]==2 and (cnt[i][j]&1)) res+=sum[i][j]-mn[i][j];
			else if(tmp[i][j]==2) res+=sum[i][j];
			else if(tmp[i][j]==1 and cnt[i][j]<1) flag=1;
			else if(tmp[i][j]==1 and (cnt[i][j]&1)) res+=sum[i][j];
			else if(tmp[i][j]==1) res+=sum[i][j]-mn[i][j];
		}
	if(flag) { tp--;  return 0; }
	for(int i=1; i<=4; i++)
	{
		if(u==i) continue;
		res=max(res,dfs(i,cur+1));
	}
	tp--; return res;
}
int main()
{	
	ios::sync_with_stdio(false); cin.tie(0);
	cin>>n;
	int w; string a,b;
	for(int i=1; i<=n; i++)
	{
		cin>>w>>a>>b;
		int u=a[0]-'W'+1,v=b[0]-'W'+1;
		if(u>v) swap(u,v); cnt[u][v]++,sum[u][v]+=w;
		if(mn[u][v]) mn[u][v]=min(mn[u][v],w);
		else mn[u][v]=w;
	}
	int ans=0;
	for(int i=1; i<=4; i++) ans=max(ans,dfs(i,1));
	printf("%d\n",ans);
	return 0;
}

C 雷与永恒的群岛 (inazuma)

DTOJ P6397

虽然刚打完稻妻任务,但是我没删调试,虽然是正解

题目大意

给定序列 {a2n}。你需要选出 n 个位置 1b1<b2<<bn2n,求 gcd(ab1,ab2,,abn) 的最大值。

对于所有测试数据,保证 1n1051ai1012

题解

O(nai) 做法

枚举 gcd,看看够不够 ngcd 的倍数

随机化乱搞 O(can AC) 做法

  1. 随机两个位置,求 gcd,塞进一个 set 里
  2. set 里随机两个位置,求 gcd,塞进 set 里

2 这个操作重复三次.

我也不知道为什么是对的,但是没有 2 可以构造出反例

代码

#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 1e5+5;
int n,m,ng;
ll a[N<<1];
set<ll> st,st2;
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
int random(int l, int r)
{
	assert(r>=l);
	return uniform_int_distribution<>(l,r)(rng);
}
int main()
{
	scanf("%d",&n); m=n<<1;
	for(int i=1; i<=m; i++) scanf("%lld",&a[i]);
	int T=100;
	ll ans=0;
	for(int i=1; i<=T; i++)
	{
		int pos1=random(1,m),pos2=random(1,m);
		st.insert(__gcd(a[pos1],a[pos2]));
	}
	for(int t=1; t<=3; t++)
	{
		st2.clear();
		for(int u:st) for(int v:st) st2.insert(__gcd(u,v));
		for(int u:st2) st.insert(u);
	}
	for(ll d:st)
	{
		int cnt=0;
		for(int i=1; i<=m; i++) if(a[i]%d==0) cnt++;
		if(cnt>=n) ans=max(ans,d);
	}
	printf("%lld\n",ans);
	return 0;
}

posted @   copper_carbonate  阅读(50)  评论(1编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示