返回上一页

7月26日2022多校冲刺NOIP联训测试6

A.Start

题面(需要密码)

大模拟,不过硬是调了好几个小时还没有调出来......

对于普通牌来说,我们可以将其对 𝑝 的作用表示为一个数对(𝑎, 𝑏),即打出这张牌后 𝑝 = ⌊𝑝 ∗ 𝑎 + 𝑏 ⌋ ,不难发现,每种牌对应的数对如下.

牌型 a b 牌型 a b
A1 1 1 B1 1 -1
A2 1 2 B9 1 -9
A5 1 5 B19 1 -19
A9 1 9 C2 2 0
A19 1 19 D2 0.5 0
A49 1 49 E0 0 0
A99 1 99 E49 0 49
E99 0 99

具体代码可以利用 𝑚𝑎𝑝 将字符串映射为点对.

对于解牌来说,因为种数很少,所以可以拿出来对每一种单独考虑.

PASS:较为简单,直接跳过即可.
TURN:使用一个变量 𝑑 来表示出牌顺序,令 𝑑 = −𝑑 .
DOUBLE:使用一个变量 𝑓 表示当前是否存在该状态.

部分实现:

	mp["A1"]=(pair<ll,ll>){ 1,1 };
	mp["A2"]=(pair<ll,ll>){ 1,2 };
	mp["A5"]=(pair<ll,ll>){ 1,5 };
	mp["A9"]=(pair<ll,ll>){ 1,9 };
	mp["A19"]=(pair<ll,ll>){ 1,19 };
	mp["A49"]=(pair<ll,ll>){ 1,49 };
	mp["A99"]=(pair<ll,ll>){ 1,99 };
	mp["B1"]=(pair<ll,ll>){ 1,-1 };
	mp["B9"]=(pair<ll,ll>){ 1,-9 };
	mp["B19"]=(pair<ll,ll>){ 1,-19 };
	mp["C2"]=(pair<ll,ll>){ 2,0 };
	mp["D2"]=(pair<ll,ll>){ 0.5,0 };
	mp["E0"]=(pair<ll,ll>){ 0,0 };
	mp["E49"]=(pair<ll,ll>){ 0,49 };
	mp["E99"]=(pair<ll,ll>){ 0,99 };
	if(w[3]<v) v=w[3],r=3;
	if(w[1]<v) v=w[1],r=1;
	if(w[0]<v) v=w[0],r=0;
	if(w[2]<v) v=w[2],r=2;
	if(w[4]<v) v=w[4],r=4;
inline bool judge()
{
	if(used("PASS")) return 1;
	if(used("TURN")) { d=-d; return 1; }
	if(used("DOUBLE")) { fl=1;return 1; };
	return 0;
}

B.Dream

题面(需要密码)

观察题目中的性质, 𝑔 和 𝑧 的个数相等,且这个串被复制了一遍.
可以发现,这三个字符串中一定存在一个子串,使得其中有n个z和n个g,且最后一个位置不是串的末尾.
证明如下,不妨设 𝑔 的位置为𝑎1,𝑎2𝑎𝑛,𝑎1+2𝑛,𝑎2+2𝑛𝑎𝑛+2𝑛,容易发现第 𝑛 个位置和第 2𝑛 个位置中间恰好有 𝑛 个 𝑧 .
因此,简单思考,我们只需先输出n个g(或n个z),再输出n个z(或n个g),最后再输出1个g(或z)即可.

#include<bits/stdc++.h>
#define ll long long
#define rg register
#define maxn 2000001
#define rll rg ll
using namespace std;
inline ll read()
{
	rll f=0,x=0;char ch=getchar();
	while(ch<'0'||ch>'9') f|=ch=='-',ch=getchar();
	while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
	return f?-x:x;
}
inline void write(ll x)
{
	if(x<0) putchar('-'),x=-x;
	if(x>9) write(x/10);putchar(x%10|48);
}
ll n;
char s[maxn];
int main()
{
	n=read();
	for(rll i=1;i<=n;i++) putchar('g');
	for(rll i=1;i<=n;i++) putchar('z');
	putchar('g');
	return 0;
}

C.It

题面(需要密码)

我们发现,如果只考虑上升的序列,这道题就很简单,就直接加,为什么下降会出现问题呢?因为下降不能直接减,下降如果直接减的话,可能会出现负数,而题意中是不允许有负数的,所以要用一下逆向思维.

怎么逆向呢?正着下降的话不就是从后往前上升吗?所以我们每次只考虑上升的,因为上升的就直接+1 就完了,于是这道题就正着跑一遍上升,倒着再跑一遍,如果这个数比前一个数大,就需要+1,小的话不管,等于也相等,最后要注意两种情况取最大值.

#include<bits/stdc++.h>
#define ll long long
#define rg register
#define maxn 1000001
#define rll rg ll
using namespace std;
inline ll read()
{
	rll f=0,x=0;char ch=getchar();
	while(ch<'0'||ch>'9') f|=ch=='-',ch=getchar();
	while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
	return f?-x:x;
}
inline void write(ll x)
{
	if(x<0) putchar('-'),x=-x;
	if(x>9) write(x/10);putchar(x%10|48);
}
ll n;
ll a[maxn];
ll ans[maxn];
ll b[maxn],cnt,c[maxn];
ll dsj[maxn],tot;
ll f1[maxn],f2[maxn];
int main()
{
	n=read();
	for(rll i=1;i<=n;i++)
	{
		cin>>a[i];
		if(a[i]==a[i-1]) b[cnt]++;
		else c[++cnt]=a[i],b[cnt]=1;
	}
	if(c[1]<c[2]) f1[1]=2,dsj[++tot]=1;
	else f1[1]=1;
	if(c[cnt]>c[cnt-1]) f1[cnt]=1;
	else f1[cnt]=2,dsj[++tot]=cnt;
	for(rll i=2;i<cnt;i++)
	{
		if(c[i]>c[i-1]&&c[i]>c[i+1]) f1[i]=1;
		else if(c[i]<c[i-1]&&c[i]<c[i+1]) f1[i]=2,dsj[++tot]=i;
	}
	for(rll i=1;i<=tot;i++)
	{
		rll id=dsj[i],w=1;
		while(id&&f1[id]!=1) f2[id--]=w++;
		f2[id]=max(f2[id],w);
		id=dsj[i];w=1;
		while(id<=cnt&&f1[id]!=1) f2[id++]=w++;
		f2[id]=max(f2[id],w);
	}
	for(rll i=1;i<=cnt;i++)
		for(rll j=1;j<=b[i];j++) write(f2[i]),putchar(' ');
	return 0;
}

D.Possible

题面(需要密码)

如果图是一棵树的话,那么答案其实是显然的.

任意图的两点间最短路貌似没有什么比Dijkstra更优的算法了,所以需要考虑这个图特有的性质,非树边是返祖边,树的深度不超过 20 ,相对来讲第二个条件的用处更为显然一些.

回忆树上最短路的求法,是由两条路径拼起来的,拼接的点为两个点的 lca,由于树的深度不超过 20,我们可以在该题中枚举两个点的拼接点是哪个,即路径上深度最小的点,注意它并不一定是 lca.

如 A 与 B 的拼接点为 C.

此时题目已经被转化成,如何求出 C 到 A 的最短路,即一个点到它子树内的某个点且不经过子树外的点的最短路,这样第一个性质似乎也变得可用起来,所有边都不是跨子树的边,所以可以依次递归每个子树进行求解.

具体的,我们按照 dfs 顺序遍历整棵树,到一个点时,将这个点子树内所有点和所有边加入到一张新图里,在新图中跑单源最短路,这样均摊时间复杂度是 20nlogn 可以通过.

接下来只要枚举这个拼接点求个最小值即可.

注意vis数组要用STL的bitset,否则会超时.

#include<bits/stdc++.h>
#define ll long long
#define rg register
#define maxn 1000001
#define rll rg ll
using namespace std;
inline ll read()
{
	rll f=0,x=0;char ch=getchar();
	while(ch<'0'||ch>'9') f|=ch=='-',ch=getchar();
	while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
	return f?-x:x;
}
inline void write(ll x)
{
	if(x<0) putchar('-'),x=-x;
	if(x>9) write(x/10);putchar(x%10|48);
}
struct node
{
	ll x,dis;
	inline friend bool operator<(rg node a,rg node b)
	{
		return a.dis>b.dis;
	}
};
ll n,m,q;
vector<pair<ll,ll> > g[maxn],g1[maxn];
ll dep[maxn],fa[maxn][11],siz[maxn],son[maxn];
ll dfn[maxn],top[maxn],cnt;
vector<ll> dcl[maxn];
priority_queue<node> que;
map<ll,ll> mp[maxn];
bitset<maxn> fl;
ll dis[maxn];
inline void dij(rll x)
{
	for(rll i=dcl[x].size()-1;i+1;i--) dis[dcl[x][i]]=0x7fffffffffffffff;
	fl.reset();
	dis[x]=0;que.push((node) { x,0 });
	while(!que.empty())
	{
		rll t=que.top().x;que.pop();
		if(fl[t]) continue;
		fl[t]=1;
		for(rll i=0;i<g1[t].size();i++)
		{
			rll to=g1[t][i].first;
			if(dis[to]>dis[t]+g1[t][i].second)
			{
				dis[to]=dis[t]+g1[t][i].second;
				que.push((node) { to,dis[to] });
			}
		}
	}
	for(rll i=dcl[x].size()-1;i+1;i--) mp[x][dcl[x][i]]=dis[dcl[x][i]];
}
inline void dfs(rll x,rll f)
{
	dep[x]=dep[f]+1;
	dcl[x].push_back(x);
	for(rll i=0;i<g[x].size();i++)
	{
		rll to=g[x][i].first;
		if(!dep[to])
		{
			fa[to][0]=x;
			for(rll j=1;j<=5;j++) fa[to][j]=fa[fa[to][j-1]][j-1];
			dfs(to,x);
			for(rll j=0;j<dcl[to].size();j++) dcl[x].push_back(dcl[to][j]);
		}
		g1[x].push_back((pair<ll,ll>) { to,g[x][i].second });
		g1[to].push_back((pair<ll,ll>) { x,g[x][i].second });
	}
	dij(x);
}
inline ll lca(rll x,rll y)
{
	if(dep[x]>dep[y])swap(x,y);
	for(int i=6;i+1;i--)if(dep[fa[y][i]]>=dep[x])y=fa[y][i];
	if(x==y)return x;
	for(int i=6;i+1;i--)if(fa[x][i]!=fa[y][i])x=fa[x][i],y=fa[y][i];
	return fa[x][0];
}
int main()
{
	n=read();m=read();q=read();
	for(rll i=1,u,v,w;i<n;i++)
	{
		u=read();v=read();w=read();
		g[u].push_back((pair<ll,ll>) { v,w });
		g[v].push_back((pair<ll,ll>) { u,w });
	}
	for(rll i=n,u,v,w;i<=m;i++)
	{
		u=read();v=read();w=read();
		g1[u].push_back((pair<ll,ll>) { v,w });
		g1[v].push_back((pair<ll,ll>) { u,w });
	}
	dfs(1,0);
	for(rll i=1,x,y;i<=q;i++)
	{
		x=read();y=read();
		rll ans=0x7fffffffffffffff;
		rll Lca=lca(x,y);
		while(Lca)
		{
			ans=min(ans,mp[Lca][x]+mp[Lca][y]);
			Lca=fa[Lca][0];
		}
		write(ans);puts("");
	}
	return 0;
}
posted @   1Liu  阅读(74)  评论(1编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示