最近没有怎么学其他的新算法,马上不是蓝桥杯了嘛,就一直在刷题,开始刷了蓝桥杯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有个数可以被表示
那就简单了
代码:
#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个珠子,容易得到转移方程
需要注意后面加的是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];
}
蓝桥杯加油!!天梯赛加油!!