2022.9.26测试
一测:
今天挺水的,不细讲
T1:P1661 扩散(黄)
T2:P2590 [ZJOI2008]树的统计(蓝)(
T3:1644:【例 4】佳佳的 Fibonacci(估计在绿左右吧)
T4:P1627 [CQOI2009] 中位数(绿)
T1:
通过模拟可知,每过
可以预处理出来两个点之间的曼哈顿距离
由于
这里选择最小生成树,对每两个点建边,边权为
时间复杂度:
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const int N=55;
int n,x[N],y[N],cnt,f[N];
struct node
{
int from,to,data;
}a[N*N];
inline int tabs(int x)
{
return x>0?x:-x;
}
int cmp(node fi,node se)
{
return fi.data<se.data;
}
int afind(int x)
{
if(f[x]==x)return x;
return f[x]=afind(f[x]);
}
int krus()
{
int res=0,num=n;
for(int i=1;i<=cnt;i++)
{
if(afind(a[i].from)==afind(a[i].to))continue;
f[afind(a[i].from)]=afind(a[i].to);
num--;
res=a[i].data;
if(num==1)break;
}
return res;
}
int main()
{
freopen("big.in","r",stdin);
freopen("big.out","w",stdout);
scanf("%d",&n);
for(int i=1;i<=n;i++)scanf("%d%d",&x[i],&y[i]),f[i]=i;
for(int i=1;i<=n;i++)
{
for(int j=i+1;j<=n;j++)
{
a[++cnt].from=i;
a[cnt].to=j;
a[cnt].data=(tabs(x[i]-x[j])+tabs(y[i]-y[j])+1)/2;
}
}
sort(a+1,a+1+cnt,cmp);
int ans=krus();
printf("%d",ans);
return 0;
}
T2:
树剖模板,注意修改点时是修改其在线段树的下标的点,样例太水没检查出来。
#include<iostream>
#include<cstdio>
#include<vector>
using namespace std;
const int N=3e4+5;
int n,dep[N],son[N],fa[N],topp[N],id[N],t[N],w[N],f[4*N],m[4*N],cnt,nl,nr,k;
vector<int>a[N];
int dfs1(int x,int fath)
{
fa[x]=fath;
dep[x]=dep[fath]+1;
int maxn=-1,sum=1;
int len=a[x].size();
for(int i=0;i<len;i++)
{
if(a[x][i]==fath)continue;
int num=dfs1(a[x][i],x);
if(num>maxn)maxn=num,son[x]=a[x][i];
sum+=num;
}
return sum;
}
void dfs2(int x,int tp)
{
id[x]=++cnt;
w[cnt]=t[x];
topp[x]=tp;
int len=a[x].size();
if(son[x])dfs2(son[x],tp);
for(int i=0;i<len;i++)
{
if(a[x][i]==fa[x]||a[x][i]==son[x])continue;
dfs2(a[x][i],a[x][i]);
}
}
inline int ls(int x)
{
return x<<1;
}
inline int rs(int x)
{
return x<<1|1;
}
inline void pushup(int x)
{
f[x]=f[ls(x)]+f[rs(x)];
m[x]=max(m[ls(x)],m[rs(x)]);
}
void build(int x,int l,int r)
{
if(l==r)
{
f[x]=m[x]=w[l];
return;
}
int mid=(l+r)>>1;
build(ls(x),l,mid);
build(rs(x),mid+1,r);
pushup(x);
}
void update(int x,int l,int r)
{
if(l==r)
{
f[x]=m[x]=k;
return;
}
int mid=(l+r)>>1;
if(mid>=nl)update(ls(x),l,mid);
else update(rs(x),mid+1,r);
pushup(x);
}
int search1(int x,int l,int r)
{
if(l>=nl&&r<=nr)return f[x];
int mid=(l+r)>>1,sum=0;
if(mid>=nl)sum+=search1(ls(x),l,mid);
if(mid<nr)sum+=search1(rs(x),mid+1,r);
return sum;
}
int search2(int x,int l,int r)
{
if(l>=nl&&r<=nr)return m[x];
int mid=(l+r)>>1,maxn=-1e9;
if(mid>=nl)maxn=max(maxn,search2(ls(x),l,mid));
if(mid<nr)maxn=max(maxn,search2(rs(x),mid+1,r));
return maxn;
}
int search1_road(int x,int y)
{
int sum=0;
while(topp[x]!=topp[y])
{
if(dep[topp[x]]<dep[topp[y]])swap(x,y);
nl=id[topp[x]],nr=id[x];
sum+=search1(1,1,n);
x=fa[topp[x]];
}
if(dep[x]>dep[y])swap(x,y);
nl=id[x],nr=id[y];
sum+=search1(1,1,n);
return sum;
}
int search2_road(int x,int y)
{
int maxn=-1e9;
while(topp[x]!=topp[y])
{
if(dep[topp[x]]<dep[topp[y]])swap(x,y);
nl=id[topp[x]],nr=id[x];
maxn=max(maxn,search2(1,1,n));
x=fa[topp[x]];
}
if(dep[x]>dep[y])swap(x,y);
nl=id[x],nr=id[y];
maxn=max(maxn,search2(1,1,n));
return maxn;
}
int main()
{
scanf("%d",&n);
for(int i=1;i<n;i++)
{
int u,v;
scanf("%d%d",&u,&v);
a[u].push_back(v);
a[v].push_back(u);
}
for(int i=1;i<=n;i++)scanf("%d",&t[i]);
dfs1(1,0);
dfs2(1,1);
build(1,1,n);
int q;
scanf("%d",&q);
for(int i=1;i<=q;i++)
{
char opt[10];
scanf("%s",opt+1);
if(opt[2]=='M')
{
int x,y;
scanf("%d%d",&x,&y);
int ans=search2_road(x,y);
printf("%d\n",ans);
}
if(opt[2]=='S')
{
int x,y;
scanf("%d%d",&x,&y);
int ans=search1_road(x,y);
printf("%d\n",ans);
}
if(opt[2]=='H')
{
scanf("%d%d",&nl,&k);
nl=id[nl];
update(1,1,n);
}
}
return 0;
}
T3:
貌似有二维斐波那契的做法,但这里讲矩阵加速。
可以很快的构造出一个初始矩阵
然后转移矩阵就很好建了
不太懂的可以自己乘一下即可。
然后求
答案即为
复杂度为
#include<iostream>
#include<cstdio>
#define int long long
using namespace std;
int n,mod;
struct matrix
{
int x,y,a[6][6];
void init()
{
for(int i=1;i<=5;i++)for(int j=1;j<=5;j++)a[i][j]=0;
}
};
matrix operator *(matrix fi,matrix se)
{
matrix th;
th.init();
th.x=fi.x,th.y=se.y;
for(int i=1;i<=fi.x;i++)
{
for(int j=1;j<=se.y;j++)
{
for(int k=1;k<=fi.y;k++)
{
th.a[i][j]+=fi.a[i][k]*se.a[k][j];
th.a[i][j]%=mod;
}
}
}
return th;
}
matrix quick_pow(matrix x,int y)
{
matrix num=x,sum;
sum.init();
sum.x=sum.y=5;
for(int i=1;i<=5;i++)sum.a[i][i]=1;
while(y)
{
if(y&1)sum=sum*num;
num=num*num;
y>>=1;
}
return sum;
}
signed main()
{
freopen("jiajia.in","r",stdin);
freopen("jiajia.out","w",stdout);
scanf("%lld%lld",&n,&mod);
if(n==1)
{
printf("1");
return 0;
}
matrix a,b;
a.init();
a.x=a.y=5,a.a[1][1]=a.a[1][2]=a.a[1][3]=a.a[1][4]=a.a[1][5]=a.a[2][2]=a.a[2][3]=a.a[2][4]=a.a[2][5]=1;
a.a[3][2]=a.a[3][4]=a.a[4][4]=a.a[4][5]=a.a[5][4]=1;
b.x=5,b.y=1;
b.a[1][1]=3,b.a[2][1]=2,b.a[3][1]=2,b.a[4][1]=1,b.a[5][1]=1;
a=quick_pow(a,n-2);
b=a*b;
printf("%lld",b.a[1][1]);
return 0;
}
T4:
思维题。
对于数
那么就预处理出来一个连续序列中比
从数
用桶记录往前遍历与往后遍历的结果,枚举一对相反数,将两边方案数相乘即可。
负数下标可以让所有的下标加上
复杂度:
#include<iostream>
#include<cstdio>
#define int long long
using namespace std;
const int N=1e5+5;
int n,k,a[N],vis1[2*N],vis2[2*N],beg;
signed main()
{
freopen("mid.in","r",stdin);
freopen("mid.out","w",stdout);
scanf("%lld%lld",&n,&k);
for(int i=1;i<=n;i++)
{
scanf("%lld",&a[i]);
if(a[i]==k)beg=i;
}
int num=0,m=N-5;
for(int i=beg;i>0;i--)
{
if(a[i]>k)num++;
if(a[i]<k)num--;
vis1[num+m]++;
}
num=0;
for(int i=beg;i<=n;i++)
{
if(a[i]>k)num++;
if(a[i]<k)num--;
vis2[num+m]++;
}
int ans=vis1[m]*vis2[m];
for(int i=0;i<m;i++)ans+=vis1[i]*vis2[2*m-i]+vis2[i]*vis1[2*m-i];
printf("%lld",ans);
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律