WEEK_2(杂题)

最近没有怎么学其他的新算法,马上不是蓝桥杯了嘛,就一直在刷题,开始刷了蓝桥杯13、23、24的题目,发现大多都不会写(哭)。然后想想还是刷其他的题目吧,把之前学的知识点复习一遍,题目:

P8605 [蓝桥杯 2013 国 AC] 网络寻路

从题目中我们可以知道,作为中间路径的两个点一定不能和起点或者终点相同,那么就固定一个中间路径,然后计算两边的路径会有多少情况能经过这个中间路径,因为独立,所以我们可以通过度来计算:

我们先给出这样一个数据:

3 3
1 2
2 3
1 3

可以看到,节点3的度为2,1的度为3,4的度为1,2的度为2,我们可以先假设3-1是中间路径(1-3暂时不用考虑),那么3和1的一条路径就被确定了,因此度减1,然后3和2连着,1还和2、4相连,故有1*2种情况,最后将每两个不同的点作为中间路径做同样的处理,并累加即可

代码:

#include<bits/stdc++.h>
using namespace std;
const long long N=1e5+5;
long long n,m;
long long ans;
long long d[N];
long long u[N],v[N];
int main()
{
	cin>>n>>m;
	for(long long i=1;i<=m;i++)
	{
		cin>>u[i]>>v[i];
		d[u[i]]++;
		d[v[i]]++;
	}
	for(long long i=1;i<=m;i++)
	if(d[u[i]]>1&&d[u[i]]>1)
	ans+=(d[u[i]]-1)*(d[v[i]]-1)*2;
	cout<<ans;
}

 P8770 [蓝桥杯 2022 省 A] 填空问题

太水了。。。

P8772 [蓝桥杯 2022 省 A] 求和

没啥难点,想到前缀和就行

#include<bits/stdc++.h>
using namespace std;
#define ll long long 
const int N=2e5+5;
int n;
int a[N];
ll s[N];
ll ans;
int main()
{
	cin>>n;
	for(int i=1;i<=n;i++)
	{
		cin>>a[i];
		s[i]=s[i-1]+a[i];
	}
	for(int i=1;i<=n;i++)
	ans+=(s[n]-s[i])*(s[i]-s[i-1]);
	cout<<ans;
}

P9230 [蓝桥杯 2023 省 A] 填空问题

23年的填空不水,A题可以暴力,B题要搜了,答案还是很好算的,A题就不说了,B题。额。搜呗

P9231 [蓝桥杯 2023 省 A] 平方差

在没思路的时候,我先去列举了一堆数字的平方差

哈哈哈,结果发现,不能被两个数平方差表示出来的是以2为首项,公差为4的等差数列,

所以可以知道从0到正整数k有k-\frac{k+4}{2}个数可以被表示

那就简单了

代码:

#include<bits/stdc++.h>
using namespace std;
int l,r;
int main()
{
	cin>>l>>r;
	cout<<(r-(r+2)/4)-(l-1-(l+1)/4);
}

P9232 [蓝桥杯 2023 省 A] 更小的数

dp!!!

我们设数组dp[i][j]代表从位置i到位置j的情况数量

如果是s[i]>s[j],那么dp的值就为1,因为此时只有将i和j交换位置这一种情况,当s[i]==s[j],那么这时dp[i][j]的值即为dp[i+1][j-1]的值

那么就有转移方程:

if(s[i]>s[j])
dp[i][j]=1;
if(s[i]==s[j])
dp[i][j]=dp[i+1][j-1]

代码:(记得逆序,否则会重复)

#include<bits/stdc++.h>
using namespace std;
const int N=3e3+5;
int dp[N][N];
string s;
int ans;
int main()
{
	cin>>s;
	for(int i=s.length()-1;i>=0;i--)
	{
		for(int j=i;j<s.length();j++)
		{
			if(s[i]>s[j])
			dp[i][j]=1;
			if(s[i]==s[j])
			dp[i][j]=dp[i+1][j-1];
			if(dp[i][j])
			ans++;
		}
	}
	cout<<ans;
}

P3178 [HAOI2015] 树上操作

突然想写一道树链剖分,写呗~~

模版题

代码:

#include<bits/stdc++.h>
using namespace std;
#define ll long long 
const int N=1e5+5;
ll n,m;
ll r,p;
ll a[N];
ll op;
ll x,q;
ll siz[N],dep[N],father[N],top[N],son[N];
//size[x]指以x为根的子树大小
//dep[x]指x的深度
//father[x]指x的父亲
//top[x]指x所有的重链的顶端 
ll id[N];
ll na[N];
ll cnt,idcnt;
ll head[N<<1];
struct ed
{
	ll to,from;
}edge[N<<1];
struct tr
{
	ll num;
	ll lazy;
	ll left;
	ll right;
}tree[N<<2];
void add(ll u,ll v)
{
	cnt++;
	edge[cnt].to=v;
	edge[cnt].from=head[u];
	head[u]=cnt;
}
void dfs1(ll u,ll fa)
{
	dep[u]=dep[fa]+1;
	siz[u]=1;
	father[u]=fa;
	for(ll i=head[u];i;i=edge[i].from)
	{
		ll v=edge[i].to;
		if(v==fa)
		continue;
		dfs1(v,u);
		siz[u]+=siz[v];
		if(!son[u]||siz[son[u]]<siz[v])
		son[u]=v;
	}
}
void dfs2(ll u,ll topx)
{
	top[u]=topx;
	idcnt++;
	id[u]=idcnt;
	na[idcnt]=a[u];
	if(!son[u])
	return ;
	dfs2(son[u],topx);
	for(ll i=head[u];i;i=edge[i].from)
	{
		ll v=edge[i].to;
		if(v!=son[u]&&v!=father[u])
		dfs2(v,v);
	}
}
void build(ll rt,ll l,ll r)
{
	tree[rt].left=l;
	tree[rt].right=r;
	tree[rt].lazy=0;
	if(l==r)
	{
		tree[rt].num=na[l];
		return ;
	}
	ll mid=(l+r)>>1;
	build(rt<<1,l,mid);
	build(rt<<1|1,mid+1,r);
	tree[rt].num=tree[rt<<1].num+tree[rt<<1|1].num;
}
void pushdown(ll rt)
{
	tree[rt<<1].num+=tree[rt].lazy*(tree[rt<<1].right-tree[rt<<1].left+1);
	tree[rt<<1|1].num+=tree[rt].lazy*(tree[rt<<1|1].right-tree[rt<<1|1].left+1);
	tree[rt<<1].lazy+=tree[rt].lazy;
	tree[rt<<1|1].lazy+=tree[rt].lazy;
	tree[rt].lazy=0;
}
void addplus(ll rt,ll x,ll a)
{
	if(tree[rt].left==tree[rt].right)
	{
		tree[rt].num+=a;
		return ;
	}
	if(tree[rt].lazy)
	pushdown(rt);
	ll mid=(tree[rt].left+tree[rt].right)>>1;
	if(x<=mid)
	addplus(rt<<1,x,a);
	else
	addplus(rt<<1|1,x,a);
	tree[rt].num=tree[rt<<1].num+tree[rt<<1|1].num;
}
void addrange(ll rt,ll x,ll y,ll a)
{
	if(tree[rt].left>=x&&tree[rt].right<=y)
	{
		tree[rt].num+=a*(tree[rt].right-tree[rt].left+1);
		tree[rt].lazy+=a;
		return ;
	}
	if(tree[rt].lazy)
	pushdown(rt);
	ll mid=(tree[rt].left+tree[rt].right)>>1;
	if(x<=mid)
	addrange(rt<<1,x,y,a);
	if(y>mid)
	addrange(rt<<1|1,x,y,a);
	tree[rt].num=tree[rt<<1].num+tree[rt<<1|1].num;
}
ll query(ll rt,ll l,ll r)
{
	ll res=0;
	if(tree[rt].left>=l&&tree[rt].right<=r)
	return tree[rt].num;
	if(tree[rt].lazy)
	pushdown(rt);
	ll mid=(tree[rt].left+tree[rt].right)>>1;
	if(l<=mid)
	res+=query(rt<<1,l,r);
	if(r>mid)
	res+=query(rt<<1|1,l,r);
	return res;
}
ll queryrange(ll xx,ll yy)
{
	ll ans=0;
	while(top[xx]!=top[yy])
	{
		if(dep[top[xx]]<dep[top[yy]])
		swap(xx,yy);
		ans+=query(1,id[top[xx]],id[xx]);
		xx=father[top[xx]];
	}
	if(dep[xx]>dep[yy])
	swap(xx,yy);
	ans+=query(1,id[xx],id[yy]);
	return ans;
}
int main()
{
	cin>>n>>m;
	for(ll i=1;i<=n;i++)
	cin>>a[i];
	for(ll i=1;i<=n-1;i++)
	{
		ll u,v;
		cin>>u>>v;
		add(u,v);
		add(v,u);
	}
	dfs1(1,0);
	dfs2(1,1);
	build(1,1,n);
	for(ll i=1;i<=m;i++)
	{
		cin>>op>>x;
		if(op==1)
		{
			cin>>q;
			addplus(1,id[x],q);
		}
		if(op==2)
		{
			cin>>q;
			addrange(1,id[x],id[x]+siz[x]-1,q);
		}
		if(op==3)
		cout<<queryrange(1,x)<<endl;
	}
}

P1063 [NOIP2006 提高组] 能量项链

一道很经典的区间dp

思路很简单:dp[i][j]代表合并i到j个珠子,容易得到转移方程

dp[j][i]=max(dp[j][i],dp[j][k]+dp[k][i]+e[j]*e[k+1]*e[i+1])

需要注意后面加的是e[k+1]而不是e[k],这是因为合并的是从j到k,k到i,那么中间的数值是第k个数的尾标记,同理e[i+1]也是这样

代码:

#include<bits/stdc++.h>
using namespace std;
const int N=205;
int dp[N][N];
int n,m;
int maxx;
int a[N];
int main()
{
	cin>>n;
	for(int i=1;i<=n;i++)
	{
		cin>>a[i];
		a[n+i]=a[i];
	}
	for(int i=2;i<n<<1;i++)
	for(int j=i-1;i-j<n&&j>=1;j--)
	for(int k=j;k<i;k++)
	{
		dp[j][i]=max(dp[j][i],dp[j][k]+dp[k+1][i]+a[j]*a[k+1]*a[i+1]);
		maxx=max(dp[j][i],maxx);
	}
	cout<<maxx;
}

P4568 [JLOI2011] 飞行路线

八百年没写dij了,索性今天没啥事儿来写一道,结果发现,自己还真的忘了咋写的了,于是反复看模版~~qwq~~,顺带着复习了优先队列堆优化,ok,完事儿

debug半小时就整出来了。。挺简单的

细说思路:

和dij的模版其实没啥区别,就是多了一个看起来有点像背包的条件:有k次免费航行的机会

那bfs里就得先遍历一遍k,然后放模版,内循环要dp!!(这很明显是要用dp写的吧)

dp[i][j]表示到达i点,有j次机会可以免机票,需要的费用。当然j一定得是>0的,并且要取最小值

代码:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define pr pair<ll,ll>
#define INF 0x3f3f3f3f
const int N=1e6+5;
ll n,m,k;
ll s,t;
ll vis[N];
ll dist[N][15];
ll cnt,head[N<<1];
ll f;
inline int read()
{
	int sum=0;
	char a=getchar();
	while(a<'0'||a>'9')
	a=getchar();
	while(a>='0'&&a<='9')
	{
		sum=(sum<<3)+(sum<<1)+a-'0';
		a=getchar();
	}
	return sum;
}
struct e
{
	ll to,from,val;
}edge[N<<1];
void add(ll u,ll v,ll w)
{
	cnt++;
	edge[cnt].to=v;
	edge[cnt].val=w;
	edge[cnt].from=head[u];
	head[u]=cnt;
}
priority_queue<pr,vector<pr>,greater<pr> >q;
void bfs()
{
	memset(dist,INF,sizeof(dist));
	for(ll j=0;j<=k;j++)
	dist[s][j]=0;
	for(ll i=0;i<=k;i++)
	{
		q.push(make_pair(s,0));
		while(!q.empty())
		{
			pr k;
			k=q.top();
			q.pop();
			ll u=k.first;
			for(ll j=head[u];j;j=edge[j].from)
			{
				ll v=edge[j].to;
				ll w=edge[j].val;
				f=0;
				if(i)
				{
					if(dist[v][i]>dist[u][i-1])
					{
						dist[v][i]=dist[u][i-1];
						f=1;
					}
				}
				if(dist[v][i]>dist[u][i]+w)
				{
					dist[v][i]=dist[u][i]+w;
					f=1;
				}
				if(f)
				q.push(make_pair(v,dist[v][i]));
			}
		}
	}
}
int main()
{
	n=read();m=read();k=read();
	s=read();t=read();
	s++,t++;
	for(ll i=1;i<=m;i++)
	{
		ll u,v,w;
		u=read();v=read();w=read();
		add(u+1,v+1,w);
		add(v+1,u+1,w);
	}
	bfs();
//	for(ll i=1;i<=n;i++)
//	{
//		for(ll j=1;j<=n;j++)
//		cout<<dist[i][j]<<" ";
//		cout<<endl;
//	}
//	
	cout<<dist[t][k];
}

蓝桥杯加油!!天梯赛加油!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值